diff options
author | Ian Lance Taylor <iant@golang.org> | 2020-07-11 12:43:49 -0700 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2020-07-11 12:43:49 -0700 |
commit | 4854d721be78358e59367982bdd94461b4be3c5a (patch) | |
tree | 8ead189e618f8ef1456c8b02c81de0cc1585d8a6 /libcpp | |
parent | 3cdc95b9f8d6c90c4a279783fd3da961c5afb22c (diff) | |
parent | e109f6e438b72ef3e403162971068d28d09b82f5 (diff) | |
download | gcc-4854d721be78358e59367982bdd94461b4be3c5a.zip gcc-4854d721be78358e59367982bdd94461b4be3c5a.tar.gz gcc-4854d721be78358e59367982bdd94461b4be3c5a.tar.bz2 |
Merge from trunk revision e109f6e438b72ef3e403162971068d28d09b82f5
Diffstat (limited to 'libcpp')
-rw-r--r-- | libcpp/ChangeLog | 100 | ||||
-rw-r--r-- | libcpp/Makefile.in | 12 | ||||
-rw-r--r-- | libcpp/aclocal.m4 | 2 | ||||
-rw-r--r-- | libcpp/charset.c | 2 | ||||
-rwxr-xr-x | libcpp/configure | 277 | ||||
-rw-r--r-- | libcpp/configure.ac | 12 | ||||
-rw-r--r-- | libcpp/directives-only.c | 240 | ||||
-rw-r--r-- | libcpp/directives.c | 44 | ||||
-rw-r--r-- | libcpp/files.c | 66 | ||||
-rw-r--r-- | libcpp/include/cpplib.h | 25 | ||||
-rw-r--r-- | libcpp/include/line-map.h | 11 | ||||
-rw-r--r-- | libcpp/init.c | 28 | ||||
-rw-r--r-- | libcpp/internal.h | 23 | ||||
-rw-r--r-- | libcpp/lex.c | 1039 | ||||
-rw-r--r-- | libcpp/macro.c | 20 | ||||
-rw-r--r-- | libcpp/po/ChangeLog | 4 | ||||
-rw-r--r-- | libcpp/po/sv.po | 6 | ||||
-rw-r--r-- | libcpp/system.h | 20 | ||||
-rw-r--r-- | libcpp/traditional.c | 6 |
19 files changed, 1304 insertions, 633 deletions
diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog index 307cf3a..ed65d15 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,3 +1,103 @@ +2020-07-07 Nathan Sidwell <nathan@acm.org> + + * directives.c (do_linemarker): Optimize rewinding to line zero. + * files.c (_cpp_stack_file): Start on line zero when about to inject + headers. + (cpp_push_include, cpp_push_default_include): Use highest_line as + the location. + * include/cpplib.h (cpp_read_main_file): Add injecting parm. + * init.c (cpp_read_main_file): Likewise, inform _cpp_stack_file. + * internal.h (enum include_type): Add IT_MAIN_INJECT. + +2020-05-29 H.J. Lu <hjl.tools@gmail.com> + + PR bootstrap/95413 + * configure: Regenerated. + +2020-05-23 David Edelsohn <dje.gcc@gmail.com> + + * Makefile.in (AR): Substitute @AR@. + * configure.ac (CHECK_PROG AR): New. + * configure: Regenerate. + +2020-05-20 Nathan Sidwell <nathan@acm.org> + + * internal.h (typedef _cpp_file): Delete, unnecessary in C++. + (enum _cpp_find_file_kind): New. + (_cpp_find_file): Use it, not 3 bools. + * files.c (_cpp_find_file): Use _cpp_find_file_kind enum, not + bools. + (cpp_make_system_header): Break overly long line. + (_cpp_stack_include, _cpp_fake_include) + (_cpp_do_file_change, _cpp_compare_file_date, _cpp_has_header): Adjust. + * init.c (cpp_read_main): Adjust _cpp_find_file call. + +2020-05-18 Nathan Sidwell <nathan@acm.org> + + * include/cpplib.h (cpp_get_otions, cpp_get_callbacks) + (cpp_get_deps): Mark as PURE. + * include/line-map.h (get_combined_adhoc_loc) + (get_location_from_adhoc_loc, get_pure_location): Reformat decls. + * internal.h (struct lexer_state): Clarify comment. + * system.h: Remove now-unneeded bool hackery. + * files.c (_cpp_find_file): Store LOC not highest_location. + + PR preprocessor/95149 + * lex.c (struct lit_accum): New. + (bufring_append): Replace by lit_accum::append. + (lex_raw_string): Reimplement, using fragments of the old version. + (lex_string): Adjust lex_raw_string call. + + PR preprocessor/95182 + * macro.c (collect_args): Preserve EOFif we fell out of the main + file. + (cpp_get_token_1): Reformat a couple of short lines. + +2020-05-14 H.J. Lu <hongjiu.lu@intel.com> + + * configure: Regenerated. + +2020-05-13 Jason Merrill <jason@redhat.com> + + * include/cpplib.h (enum c_lang): Change CXX2A to CXX20. + * init.c, lex.c: Adjust. + +2020-05-12 Nathan Sidwell <nathan@acm.org> + + EOF location is at end of file + PR preprocessor/95013 + * lex.c (lex_raw_string): Process line notes before incrementing. + Correct incrementing condition. Adjust for new + _cpp_get_fresh_line EOF behaviour. + (_cpp_get_fresh_line): Do not pop buffer at EOF, increment line + instead. + (_cpp_lex_direct): Adjust for new _cpp_get_fresh_line behaviour. + (cpp_directive_only_process): Assert we got a fresh line. + * traditional.c (_cpp_read_logical_line_trad): Adjust for new + _cpp_get_fresh_line behaviour. + +2020-05-12 H.J. Lu <hongjiu.lu@intel.com> + + * Makefile.in (CET_HOST_FLAGS): New. + (COMPILER): Add $(CET_HOST_FLAGS). + * configure.ac: Add GCC_CET_HOST_FLAGS(CET_HOST_FLAGS) and + AC_SUBST(CET_HOST_FLAGS). Clear CET_HOST_FLAGS if jit isn't + enabled. + * aclocal.m4: Regenerated. + * configure: Likewise. + +2020-05-08 Nathan Sidwell <nathan@acm.org> + + Reimplement directives only processing, support raw literals. + * directives-only.c: Delete. + * Makefile.in (libcpp_a_OBJS, libcpp_a_SOURCES): Remove it. + * include/cpplib.h (enum CPP_DO_task): New enum. + (cpp_directive_only_preprocess): Declare. + * internal.h (_cpp_dir_only_callbacks): Delete. + (_cpp_preprocess_dir_only): Delete. + * lex.c (do_peek_backslask, do_peek_next, do_peek_prev): New. + (cpp_directives_only_process): New implementation. + 2020-02-14 Jakub Jelinek <jakub@redhat.com> Partially implement P1042R1: __VA_OPT__ wording clarifications diff --git a/libcpp/Makefile.in b/libcpp/Makefile.in index 8f8c8f6..5fbba9b 100644 --- a/libcpp/Makefile.in +++ b/libcpp/Makefile.in @@ -25,7 +25,7 @@ srcdir = @srcdir@ top_builddir = . VPATH = @srcdir@ INSTALL = @INSTALL@ -AR = ar +AR = @AR@ ARFLAGS = cru ACLOCAL = @ACLOCAL@ AUTOCONF = @AUTOCONF@ @@ -58,6 +58,7 @@ CXXDEPMODE = @CXXDEPMODE@ DEPDIR = @DEPDIR@ NOEXCEPTION_FLAGS = @noexception_flags@ PICFLAG = @PICFLAG@ +CET_HOST_FLAGS = @CET_HOST_FLAGS@ datarootdir = @datarootdir@ datadir = @datadir@ @@ -73,9 +74,10 @@ depcomp = $(SHELL) $(srcdir)/../depcomp INCLUDES = -I$(srcdir) -I. -I$(srcdir)/../include @INCINTL@ \ -I$(srcdir)/include -ALL_CFLAGS = $(CFLAGS) $(WARN_CFLAGS) $(INCLUDES) $(CPPFLAGS) $(PICFLAG) +ALL_CFLAGS = $(CFLAGS) $(WARN_CFLAGS) $(INCLUDES) $(CPPFLAGS) $(PICFLAG) \ + $(CET_HOST_FLAGS) ALL_CXXFLAGS = $(CXXFLAGS) $(WARN_CXXFLAGS) $(NOEXCEPTION_FLAGS) $(INCLUDES) \ - $(CPPFLAGS) $(PICFLAG) + $(CPPFLAGS) $(PICFLAG) $(CET_HOST_FLAGS) # The name of the compiler to use. COMPILER = $(CXX) @@ -83,11 +85,11 @@ COMPILER_FLAGS = $(ALL_CXXFLAGS) DEPMODE = $(CXXDEPMODE) -libcpp_a_OBJS = charset.o directives.o directives-only.o errors.o \ +libcpp_a_OBJS = charset.o directives.o errors.o \ expr.o files.o identifiers.o init.o lex.o line-map.o macro.o \ mkdeps.o pch.o symtab.o traditional.o -libcpp_a_SOURCES = charset.c directives.c directives-only.c errors.c \ +libcpp_a_SOURCES = charset.c directives.c errors.c \ expr.c files.c identifiers.c init.c lex.c line-map.c macro.c \ mkdeps.c pch.c symtab.c traditional.c diff --git a/libcpp/aclocal.m4 b/libcpp/aclocal.m4 index 46bb65a..70c3eff 100644 --- a/libcpp/aclocal.m4 +++ b/libcpp/aclocal.m4 @@ -13,8 +13,10 @@ m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) m4_include([../config/acx.m4]) +m4_include([../config/cet.m4]) m4_include([../config/codeset.m4]) m4_include([../config/depstand.m4]) +m4_include([../config/enable.m4]) m4_include([../config/gettext-sister.m4]) m4_include([../config/iconv.m4]) m4_include([../config/lead-dot.m4]) diff --git a/libcpp/charset.c b/libcpp/charset.c index d9281c5..db47235 100644 --- a/libcpp/charset.c +++ b/libcpp/charset.c @@ -1021,7 +1021,7 @@ ucn_valid_in_identifier (cpp_reader *pfile, cppchar_t c, If the hexadecimal value is larger than the upper bound of the UCS codespace specified in ISO/IEC 10646, a pedantic warning is issued - in all versions of C and in the C++2a or later versions of C++. + in all versions of C and in the C++20 or later versions of C++. *PSTR must be preceded by "\u" or "\U"; it is assumed that the buffer end is delimited by a non-hex digit. Returns false if the diff --git a/libcpp/configure b/libcpp/configure index 11da199..3329e20 100755 --- a/libcpp/configure +++ b/libcpp/configure @@ -623,6 +623,7 @@ ac_includes_default="\ #endif" ac_subst_vars='LTLIBOBJS +CET_HOST_FLAGS PICFLAG MAINT USED_CATALOGS @@ -657,6 +658,7 @@ ACLOCAL EGREP GREP CPP +AR RANLIB ac_ct_CXX CXXFLAGS @@ -735,6 +737,7 @@ enable_maintainer_mode enable_checking enable_canonical_system_headers enable_host_shared +enable_cet enable_valgrind_annotations ' ac_precious_vars='build_alias @@ -1375,6 +1378,7 @@ Optional Features: --enable-canonical-system-headers enable or disable system headers canonicalization --enable-host-shared build host code as shared libraries + --enable-cet enable Intel CET in host libraries [default=auto] --enable-valgrind-annotations enable valgrind runtime interaction @@ -4008,6 +4012,98 @@ else RANLIB="$ac_cv_prog_RANLIB" fi +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. +set dummy ${ac_tool_prefix}ar; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AR="${ac_tool_prefix}ar" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +$as_echo "$AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_AR"; then + ac_ct_AR=$AR + # Extract the first word of "ar", so it can be a program name with args. +set dummy ar; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_AR="ar" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 +$as_echo "$ac_ct_AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_AR" = x; then + AR="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + AR=$ac_ct_AR + fi +else + AR="$ac_cv_prog_AR" +fi + ac_ext=c @@ -7443,6 +7539,187 @@ fi +# Enable Intel CET on Intel CET enabled host if jit is enabled. + # Check whether --enable-cet was given. +if test "${enable_cet+set}" = set; then : + enableval=$enable_cet; + case "$enableval" in + yes|no|auto) ;; + *) as_fn_error $? "Unknown argument to enable/disable cet" "$LINENO" 5 ;; + esac + +else + enable_cet=auto +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for CET support" >&5 +$as_echo_n "checking for CET support... " >&6; } + +case "$host" in + i[34567]86-*-linux* | x86_64-*-linux*) + may_have_cet=yes + cet_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -fcf-protection" + case "$enable_cet" in + auto) + # Check if target supports multi-byte NOPs + # and if assembler supports CET insn. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + +#if !defined(__SSE2__) +#error target does not support multi-byte NOPs +#else +asm ("setssbsy"); +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + enable_cet=yes +else + enable_cet=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ;; + yes) + # Check if assembler supports CET. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +asm ("setssbsy"); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + as_fn_error $? "assembler with CET support is required for --enable-cet" "$LINENO" 5 +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ;; + esac + CFLAGS="$cet_save_CFLAGS" + ;; + *) + may_have_cet=no + enable_cet=no + ;; +esac + +cet_save_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS -fcf-protection=none" +cet_save_LDFLAGS="$LDFLAGS" +LDFLAGS="$LDFLAGS -Wl,-z,ibt,-z,shstk" +if test x$may_have_cet = xyes; then + # Check whether -fcf-protection=none -Wl,-z,ibt,-z,shstk work. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + may_have_cet=yes +else + may_have_cet=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi + +if test x$may_have_cet = xyes; then + if test x$cross_compiling = xno; then + if test "$cross_compiling" = yes; then : + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run test program while cross compiling +See \`config.log' for more details" "$LINENO" 5; } +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +static void +foo (void) +{ +} + +static void +__attribute__ ((noinline, noclone)) +xxx (void (*f) (void)) +{ + f (); +} + +static void +__attribute__ ((noinline, noclone)) +bar (void) +{ + xxx (foo); +} + +int +main () +{ + bar (); + return 0; +} + +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + have_cet=no +else + have_cet=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + if test x$enable_cet = xno -a x$have_cet = xyes; then + as_fn_error $? "Intel CET must be enabled on Intel CET enabled host" "$LINENO" 5 + fi + fi +else + # Enable CET in cross compiler if possible so that it will run on both + # CET and non-CET hosts. + have_cet=yes +fi +if test x$enable_cet = xyes; then + CET_HOST_FLAGS="-fcf-protection" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +CFLAGS="$cet_save_CFLAGS" +LDFLAGS="$cet_save_LDFLAGS" + +case x$enable_languages in +*jit*) + ;; +*) + CET_HOST_FLAGS= + ;; +esac + + # Check whether --enable-valgrind-annotations was given. if test "${enable_valgrind_annotations+set}" = set; then : enableval=$enable_valgrind_annotations; diff --git a/libcpp/configure.ac b/libcpp/configure.ac index 1779562..1efa96f 100644 --- a/libcpp/configure.ac +++ b/libcpp/configure.ac @@ -12,6 +12,7 @@ AC_PROG_INSTALL AC_PROG_CC AC_PROG_CXX AC_PROG_RANLIB +AC_CHECK_TOOL(AR, ar) AC_USE_SYSTEM_EXTENSIONS AC_SYS_LARGEFILE @@ -206,6 +207,17 @@ AC_ARG_ENABLE(host-shared, [PICFLAG=-fPIC], [PICFLAG=]) AC_SUBST(PICFLAG) +# Enable Intel CET on Intel CET enabled host if jit is enabled. +GCC_CET_HOST_FLAGS(CET_HOST_FLAGS) +case x$enable_languages in +*jit*) + ;; +*) + CET_HOST_FLAGS= + ;; +esac +AC_SUBST(CET_HOST_FLAGS) + AC_ARG_ENABLE(valgrind-annotations, [AS_HELP_STRING([--enable-valgrind-annotations], [enable valgrind runtime interaction])], [], diff --git a/libcpp/directives-only.c b/libcpp/directives-only.c deleted file mode 100644 index 5eac118..0000000 --- a/libcpp/directives-only.c +++ /dev/null @@ -1,240 +0,0 @@ -/* CPP Library - directive only preprocessing for distributed compilation. - Copyright (C) 2007-2020 Free Software Foundation, Inc. - Contributed by Ollie Wild <aaw@google.com>. - -This program is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 3, or (at your option) any -later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; see the file COPYING3. If not see -<http://www.gnu.org/licenses/>. */ - -#include "config.h" -#include "system.h" -#include "cpplib.h" -#include "internal.h" - -/* DO (Directive only) flags. */ -#define DO_BOL (1 << 0) /* At the beginning of a logical line. */ -#define DO_STRING (1 << 1) /* In a string constant. */ -#define DO_CHAR (1 << 2) /* In a character constant. */ -#define DO_BLOCK_COMMENT (1 << 3) /* In a block comment. */ -#define DO_LINE_COMMENT (1 << 4) /* In a single line "//-style" comment. */ - -#define DO_LINE_SPECIAL (DO_STRING | DO_CHAR | DO_LINE_COMMENT) -#define DO_SPECIAL (DO_LINE_SPECIAL | DO_BLOCK_COMMENT) - -/* Writes out the preprocessed file, handling spacing and paste - avoidance issues. */ -void -_cpp_preprocess_dir_only (cpp_reader *pfile, - const struct _cpp_dir_only_callbacks *cb) -{ - struct cpp_buffer *buffer; - const unsigned char *cur, *base, *next_line, *rlimit; - cppchar_t c, last_c; - unsigned flags; - linenum_type lines; - int col; - location_t loc; - - restart: - /* Buffer initialization ala _cpp_clean_line(). */ - buffer = pfile->buffer; - buffer->cur_note = buffer->notes_used = 0; - buffer->cur = buffer->line_base = buffer->next_line; - buffer->need_line = false; - - /* This isn't really needed. It prevents a compiler warning, though. */ - loc = pfile->line_table->highest_line; - - /* Scan initialization. */ - next_line = cur = base = buffer->cur; - rlimit = buffer->rlimit; - flags = DO_BOL; - lines = 0; - col = 1; - - for (last_c = '\n', c = *cur; cur < rlimit; last_c = c, c = *++cur, ++col) - { - /* Skip over escaped newlines. */ - if (__builtin_expect (c == '\\', false)) - { - const unsigned char *tmp = cur + 1; - - while (is_nvspace (*tmp) && tmp < rlimit) - tmp++; - if (*tmp == '\r') - tmp++; - if (*tmp == '\n' && tmp < rlimit) - { - CPP_INCREMENT_LINE (pfile, 0); - lines++; - col = 0; - cur = tmp; - c = last_c; - continue; - } - } - - if (__builtin_expect (last_c == '#', false) && !(flags & DO_SPECIAL)) - { - if (c != '#' && (flags & DO_BOL)) - { - class line_maps *line_table; - - if (!pfile->state.skipping && next_line != base) - cb->print_lines (lines, base, next_line - base); - - /* Prep things for directive handling. */ - buffer->next_line = cur; - buffer->need_line = true; - _cpp_get_fresh_line (pfile); - - /* Ensure proper column numbering for generated error messages. */ - buffer->line_base -= col - 1; - - _cpp_handle_directive (pfile, false /* ignore indented */); - - /* Sanitize the line settings. Duplicate #include's can mess - things up. */ - line_table = pfile->line_table; - line_table->highest_location = line_table->highest_line; - - /* The if block prevents us from outputing line information when - the file ends with a directive and no newline. Note that we - must use pfile->buffer, not buffer. */ - if (pfile->buffer->next_line < pfile->buffer->rlimit) - cb->maybe_print_line (pfile->line_table->highest_line); - - goto restart; - } - - flags &= ~DO_BOL; - pfile->mi_valid = false; - } - else if (__builtin_expect (last_c == '/', false) \ - && !(flags & DO_SPECIAL) && c != '*' && c != '/') - { - /* If a previous slash is not starting a block comment, clear the - DO_BOL flag. */ - flags &= ~DO_BOL; - pfile->mi_valid = false; - } - - switch (c) - { - case '/': - if ((flags & DO_BLOCK_COMMENT) && last_c == '*') - { - flags &= ~DO_BLOCK_COMMENT; - c = 0; - } - else if (!(flags & DO_SPECIAL) && last_c == '/') - flags |= DO_LINE_COMMENT; - else if (!(flags & DO_SPECIAL)) - /* Mark the position for possible error reporting. */ - loc = linemap_position_for_column (pfile->line_table, col); - - break; - - case '*': - if (!(flags & DO_SPECIAL)) - { - if (last_c == '/') - flags |= DO_BLOCK_COMMENT; - else - { - flags &= ~DO_BOL; - pfile->mi_valid = false; - } - } - - break; - - case '\'': - case '"': - { - unsigned state = (c == '"') ? DO_STRING : DO_CHAR; - - if (!(flags & DO_SPECIAL)) - { - flags |= state; - flags &= ~DO_BOL; - pfile->mi_valid = false; - } - else if ((flags & state) && last_c != '\\') - flags &= ~state; - - break; - } - - case '\\': - { - if ((flags & (DO_STRING | DO_CHAR)) && last_c == '\\') - c = 0; - - if (!(flags & DO_SPECIAL)) - { - flags &= ~DO_BOL; - pfile->mi_valid = false; - } - - break; - } - - case '\n': - CPP_INCREMENT_LINE (pfile, 0); - lines++; - col = 0; - flags &= ~DO_LINE_SPECIAL; - if (!(flags & DO_SPECIAL)) - flags |= DO_BOL; - break; - - case '#': - next_line = cur; - /* Don't update DO_BOL yet. */ - break; - - case ' ': case '\t': case '\f': case '\v': case '\0': - break; - - default: - if (!(flags & DO_SPECIAL)) - { - flags &= ~DO_BOL; - pfile->mi_valid = false; - } - break; - } - } - - if (flags & DO_BLOCK_COMMENT) - cpp_error_with_line (pfile, CPP_DL_ERROR, loc, 0, "unterminated comment"); - - if (!pfile->state.skipping && cur != base) - { - /* If the file was not newline terminated, add rlimit, which is - guaranteed to point to a newline, to the end of our range. */ - if (cur[-1] != '\n') - { - cur++; - CPP_INCREMENT_LINE (pfile, 0); - lines++; - } - - cb->print_lines (lines, base, cur - base); - } - - _cpp_pop_buffer (pfile); - if (pfile->buffer) - goto restart; -} diff --git a/libcpp/directives.c b/libcpp/directives.c index bbfdfcd..f597187 100644 --- a/libcpp/directives.c +++ b/libcpp/directives.c @@ -940,7 +940,7 @@ strtolinenum (const uchar *str, size_t len, linenum_type *nump, bool *wrapped) /* Interpret #line command. Note that the filename string (if any) is a true string constant - (escapes are interpreted), unlike in #line. */ + (escapes are interpreted). */ static void do_line (cpp_reader *pfile) { @@ -1115,27 +1115,43 @@ do_linemarker (cpp_reader *pfile) line_table->seen_line_directive = true; } -/* Arrange the file_change callback. pfile->line has changed to - FILE_LINE of TO_FILE, for reason REASON. SYSP is 1 for a system - header, 2 for a system header that needs to be extern "C" protected, - and zero otherwise. */ +/* Arrange the file_change callback. Changing to TO_FILE:TO_LINE for + REASON. SYSP is 1 for a system header, 2 for a system header that + needs to be extern "C" protected, and zero otherwise. */ void _cpp_do_file_change (cpp_reader *pfile, enum lc_reason reason, - const char *to_file, linenum_type file_line, + const char *to_file, linenum_type to_line, unsigned int sysp) { linemap_assert (reason != LC_ENTER_MACRO); - const struct line_map *map = linemap_add (pfile->line_table, reason, sysp, - to_file, file_line); + const line_map_ordinary *ord_map = NULL; - if (map != NULL) - { - ord_map = linemap_check_ordinary (map); - linemap_line_start (pfile->line_table, - ORDINARY_MAP_STARTING_LINE_NUMBER (ord_map), - 127); + if (!to_line && reason == LC_RENAME_VERBATIM) + { + /* A linemarker moving to line zero. If we're on the second + line of the current map, and it also starts at zero, just + rewind -- we're probably reading the builtins of a + preprocessed source. */ + line_map_ordinary *last = LINEMAPS_LAST_ORDINARY_MAP (pfile->line_table); + if (!ORDINARY_MAP_STARTING_LINE_NUMBER (last) + && SOURCE_LINE (last, pfile->line_table->highest_line) == 2) + { + ord_map = last; + pfile->line_table->highest_location + = pfile->line_table->highest_line = MAP_START_LOCATION (last); + } } + if (!ord_map) + if (const line_map *map = linemap_add (pfile->line_table, reason, sysp, + to_file, to_line)) + { + ord_map = linemap_check_ordinary (map); + linemap_line_start (pfile->line_table, + ORDINARY_MAP_STARTING_LINE_NUMBER (ord_map), + 127); + } + if (pfile->cb.file_change) pfile->cb.file_change (pfile, ord_map); } diff --git a/libcpp/files.c b/libcpp/files.c index 260e787..3d48c38 100644 --- a/libcpp/files.c +++ b/libcpp/files.c @@ -496,21 +496,16 @@ _cpp_find_failed (_cpp_file *file) had previously been closed. To open it again pass the return value to open_file(). - If IMPLICIT_PREINCLUDE then it is OK for the file to be missing. - If present, it is OK for a precompiled header to be included after - it. + If KIND is _cpp_FFK_PRE_INCLUDE then it is OK for the file to be + missing. If present, it is OK for a precompiled header to be + included after it. Use LOC as the location for any errors. */ _cpp_file * _cpp_find_file (cpp_reader *pfile, const char *fname, cpp_dir *start_dir, - int angle_brackets, - bool fake, bool implicit_preinclude, bool has_include, - location_t loc) + int angle_brackets, _cpp_find_file_kind kind, location_t loc) { - struct cpp_file_hash_entry *entry; - void **hash_slot; - _cpp_file *file; bool invalid_pch = false; bool saw_bracket_include = false; bool saw_quote_include = false; @@ -520,22 +515,22 @@ _cpp_find_file (cpp_reader *pfile, const char *fname, cpp_dir *start_dir, if (start_dir == NULL) cpp_error_at (pfile, CPP_DL_ICE, loc, "NULL directory in find_file"); - hash_slot + void **hash_slot = htab_find_slot_with_hash (pfile->file_hash, fname, htab_hash_string (fname), INSERT); /* First check the cache before we resort to memory allocation. */ - entry = search_cache ((struct cpp_file_hash_entry *) *hash_slot, start_dir); + cpp_file_hash_entry *entry + = search_cache ((struct cpp_file_hash_entry *) *hash_slot, start_dir); if (entry) return entry->u.file; - file = make_cpp_file (pfile, start_dir, fname); + _cpp_file *file = make_cpp_file (pfile, start_dir, fname); file->implicit_preinclude - = (implicit_preinclude - || (pfile->buffer - && pfile->buffer->file->implicit_preinclude)); + = (kind == _cpp_FFK_PRE_INCLUDE + || (pfile->buffer && pfile->buffer->file->implicit_preinclude)); - if (!fake) + if (kind != _cpp_FFK_FAKE) /* Try each path in the include chain. */ for (;;) { @@ -580,7 +575,7 @@ _cpp_find_file (cpp_reader *pfile, const char *fname, cpp_dir *start_dir, "use -Winvalid-pch for more information"); } - if (implicit_preinclude) + if (kind == _cpp_FFK_PRE_INCLUDE) { free ((char *) file->name); free (file); @@ -593,7 +588,7 @@ _cpp_find_file (cpp_reader *pfile, const char *fname, cpp_dir *start_dir, return NULL; } - if (!has_include) + if (kind != _cpp_FFK_HAS_INCLUDE) open_file_failed (pfile, file, angle_brackets, loc); break; } @@ -635,7 +630,7 @@ _cpp_find_file (cpp_reader *pfile, const char *fname, cpp_dir *start_dir, entry = new_file_hash_entry (pfile); entry->next = (struct cpp_file_hash_entry *) *hash_slot; entry->start_dir = start_dir; - entry->location = pfile->line_table->highest_location; + entry->location = loc; entry->u.file = file; *hash_slot = (void *) entry; @@ -648,7 +643,7 @@ _cpp_find_file (cpp_reader *pfile, const char *fname, cpp_dir *start_dir, entry = new_file_hash_entry (pfile); entry->next = (struct cpp_file_hash_entry *) *hash_slot; entry->start_dir = pfile->bracket_include; - entry->location = pfile->line_table->highest_location; + entry->location = loc; entry->u.file = file; *hash_slot = (void *) entry; } @@ -659,7 +654,7 @@ _cpp_find_file (cpp_reader *pfile, const char *fname, cpp_dir *start_dir, entry = new_file_hash_entry (pfile); entry->next = (struct cpp_file_hash_entry *) *hash_slot; entry->start_dir = pfile->quote_include; - entry->location = pfile->line_table->highest_location; + entry->location = loc; entry->u.file = file; *hash_slot = (void *) entry; } @@ -952,7 +947,11 @@ _cpp_stack_file (cpp_reader *pfile, _cpp_file *file, include_type type, pfile->line_table->highest_location--; /* Add line map and do callbacks. */ - _cpp_do_file_change (pfile, LC_ENTER, file->path, 1, sysp); + _cpp_do_file_change (pfile, LC_ENTER, file->path, + /* With preamble injection, start on line zero, so + the preamble doesn't appear to have been + included from line 1. */ + type == IT_MAIN_INJECT ? 0 : 1, sysp); return true; } @@ -1049,7 +1048,8 @@ _cpp_stack_include (cpp_reader *pfile, const char *fname, int angle_brackets, return false; _cpp_file *file = _cpp_find_file (pfile, fname, dir, angle_brackets, - false, type == IT_DEFAULT, false, loc); + type == IT_DEFAULT ? _cpp_FFK_PRE_INCLUDE + : _cpp_FFK_NORMAL, loc); if (type == IT_DEFAULT && file == NULL) return false; @@ -1342,8 +1342,7 @@ cpp_clear_file_cache (cpp_reader *pfile) void _cpp_fake_include (cpp_reader *pfile, const char *fname) { - _cpp_find_file (pfile, fname, pfile->buffer->file->dir, - 0, true, false, false, 0); + _cpp_find_file (pfile, fname, pfile->buffer->file->dir, 0, _cpp_FFK_FAKE, 0); } /* Not everyone who wants to set system-header-ness on a buffer can @@ -1360,7 +1359,8 @@ cpp_make_system_header (cpp_reader *pfile, int syshdr, int externc) flags = 1 + (externc != 0); pfile->buffer->sysp = flags; _cpp_do_file_change (pfile, LC_RENAME, ORDINARY_MAP_FILE_NAME (map), - SOURCE_LINE (map, pfile->line_table->highest_line), flags); + SOURCE_LINE (map, pfile->line_table->highest_line), + flags); } /* Allow the client to change the current file. Used by the front end @@ -1461,8 +1461,7 @@ _cpp_compare_file_date (cpp_reader *pfile, const char *fname, if (!dir) return -1; - file = _cpp_find_file (pfile, fname, dir, angle_brackets, - false, false, false, 0); + file = _cpp_find_file (pfile, fname, dir, angle_brackets, _cpp_FFK_NORMAL, 0); if (file->err_no) return -1; @@ -1480,7 +1479,8 @@ _cpp_compare_file_date (cpp_reader *pfile, const char *fname, bool cpp_push_include (cpp_reader *pfile, const char *fname) { - return _cpp_stack_include (pfile, fname, false, IT_CMDLINE, 0); + return _cpp_stack_include (pfile, fname, false, IT_CMDLINE, + pfile->line_table->highest_line); } /* Pushes the given file, implicitly included at the start of a @@ -1489,7 +1489,8 @@ cpp_push_include (cpp_reader *pfile, const char *fname) bool cpp_push_default_include (cpp_reader *pfile, const char *fname) { - return _cpp_stack_include (pfile, fname, true, IT_DEFAULT, 0); + return _cpp_stack_include (pfile, fname, true, IT_DEFAULT, + pfile->line_table->highest_line); } /* Do appropriate cleanup when a file INC's buffer is popped off the @@ -2006,10 +2007,7 @@ _cpp_has_header (cpp_reader *pfile, const char *fname, int angle_brackets, { cpp_dir *start_dir = search_path_head (pfile, fname, angle_brackets, type); _cpp_file *file = _cpp_find_file (pfile, fname, start_dir, angle_brackets, - /*fake=*/false, - /*implicit_preinclude=*/false, - /*has_include=*/true, - 0); + _cpp_FFK_HAS_INCLUDE, 0); return file->err_no != ENOENT; } diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h index 03cc72a..e8bb15d 100644 --- a/libcpp/include/cpplib.h +++ b/libcpp/include/cpplib.h @@ -173,7 +173,7 @@ enum c_lang {CLK_GNUC89 = 0, CLK_GNUC99, CLK_GNUC11, CLK_GNUC17, CLK_GNUC2X, CLK_STDC2X, CLK_GNUCXX, CLK_CXX98, CLK_GNUCXX11, CLK_CXX11, CLK_GNUCXX14, CLK_CXX14, CLK_GNUCXX17, CLK_CXX17, - CLK_GNUCXX2A, CLK_CXX2A, CLK_ASM}; + CLK_GNUCXX20, CLK_CXX20, CLK_ASM}; /* Payload of a NUMBER, STRING, CHAR or COMMENT token. */ struct GTY(()) cpp_string { @@ -484,7 +484,7 @@ struct cpp_options /* Nonzero for C2X decimal floating-point constants. */ unsigned char dfp_constants; - /* Nonzero for C++2a __VA_OPT__ feature. */ + /* Nonzero for C++20 __VA_OPT__ feature. */ unsigned char va_opt; /* Nonzero for the '::' token. */ @@ -969,17 +969,18 @@ extern void cpp_set_include_chains (cpp_reader *, cpp_dir *, cpp_dir *, int); call cpp_finish on that reader. You can either edit the callbacks through the pointer returned from cpp_get_callbacks, or set them with cpp_set_callbacks. */ -extern cpp_options *cpp_get_options (cpp_reader *); -extern cpp_callbacks *cpp_get_callbacks (cpp_reader *); +extern cpp_options *cpp_get_options (cpp_reader *) ATTRIBUTE_PURE; +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 *); +extern class mkdeps *cpp_get_deps (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 least one file change callback, and possibly a line change callback too. If there was an error opening the file, it returns NULL. */ -extern const char *cpp_read_main_file (cpp_reader *, const char *); +extern const char *cpp_read_main_file (cpp_reader *, const char *, + bool injecting = false); /* Set up built-ins with special behavior. Use cpp_init_builtins() instead unless your know what you are doing. */ @@ -1304,6 +1305,18 @@ extern int cpp_read_state (cpp_reader *, const char *, FILE *, /* In lex.c */ extern void cpp_force_token_locations (cpp_reader *, location_t); extern void cpp_stop_forcing_token_locations (cpp_reader *); +enum CPP_DO_task +{ + CPP_DO_print, + CPP_DO_location, + CPP_DO_token +}; + +extern void cpp_directive_only_process (cpp_reader *pfile, + void *data, + void (*cb) (cpp_reader *, + CPP_DO_task, + void *data, ...)); /* In expr.c */ extern enum cpp_ttype cpp_userdef_string_remove_type diff --git a/libcpp/include/line-map.h b/libcpp/include/line-map.h index dbbc137..217f916 100644 --- a/libcpp/include/line-map.h +++ b/libcpp/include/line-map.h @@ -1024,13 +1024,11 @@ LINEMAPS_LAST_ALLOCATED_MACRO_MAP (const line_maps *set) return (line_map_macro *)LINEMAPS_LAST_ALLOCATED_MAP (set, true); } -extern location_t get_combined_adhoc_loc (class line_maps *, - location_t, - source_range, - void *); +extern location_t get_combined_adhoc_loc (line_maps *, location_t, + source_range, void *); extern void *get_data_from_adhoc_loc (const line_maps *, location_t); extern location_t get_location_from_adhoc_loc (const line_maps *, - location_t); + location_t); extern source_range get_range_from_loc (line_maps *set, location_t loc); @@ -1043,8 +1041,7 @@ pure_location_p (line_maps *set, location_t loc); /* Given location LOC within SET, strip away any packed range information or ad-hoc information. */ -extern location_t get_pure_location (line_maps *set, - location_t loc); +extern location_t get_pure_location (line_maps *set, location_t loc); /* Combine LOC and BLOCK, giving a combined adhoc location. */ diff --git a/libcpp/init.c b/libcpp/init.c index a3cd8e2..d641d0a1 100644 --- a/libcpp/init.c +++ b/libcpp/init.c @@ -117,8 +117,8 @@ static const struct lang_flags lang_defaults[] = /* CXX14 */ { 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0 }, /* GNUCXX17 */ { 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0 }, /* CXX17 */ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0 }, - /* GNUCXX2A */ { 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0 }, - /* CXX2A */ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0 }, + /* GNUCXX20 */ { 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0 }, + /* CXX20 */ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0 }, /* ASM */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; @@ -533,8 +533,8 @@ cpp_init_builtins (cpp_reader *pfile, int hosted) if (CPP_OPTION (pfile, cplusplus)) { - if (CPP_OPTION (pfile, lang) == CLK_CXX2A - || CPP_OPTION (pfile, lang) == CLK_GNUCXX2A) + if (CPP_OPTION (pfile, lang) == CLK_CXX20 + || CPP_OPTION (pfile, lang) == CLK_GNUCXX20) _cpp_define_builtin (pfile, "__cplusplus 201709L"); else if (CPP_OPTION (pfile, lang) == CLK_CXX17 || CPP_OPTION (pfile, lang) == CLK_GNUCXX17) @@ -657,13 +657,12 @@ cpp_post_options (cpp_reader *pfile) } /* Setup for processing input from the file named FNAME, or stdin if - it is the empty string. Return the original filename - on success (e.g. foo.i->foo.c), or NULL on failure. */ + it is the empty string. Return the original filename on success + (e.g. foo.i->foo.c), or NULL on failure. INJECTING is true if + there may be injected headers before line 1 of the main file. */ const char * -cpp_read_main_file (cpp_reader *pfile, const char *fname) +cpp_read_main_file (cpp_reader *pfile, const char *fname, bool injecting) { - const location_t loc = 0; - if (CPP_OPTION (pfile, deps.style) != DEPS_NONE) { if (!pfile->deps) @@ -675,21 +674,20 @@ cpp_read_main_file (cpp_reader *pfile, const char *fname) pfile->main_file = _cpp_find_file (pfile, fname, &pfile->no_search_path, /*angle=*/0, - /*fake=*/false, /*preinclude=*/false, /*hasinclude=*/false, - loc); + _cpp_FFK_NORMAL, 0); if (_cpp_find_failed (pfile->main_file)) return NULL; - _cpp_stack_file (pfile, pfile->main_file, IT_MAIN, 0); + _cpp_stack_file (pfile, pfile->main_file, + injecting ? IT_MAIN_INJECT : IT_MAIN, 0); /* For foo.i, read the original filename foo.c now, for the benefit of the front ends. */ if (CPP_OPTION (pfile, preprocessed)) { read_original_filename (pfile); - fname = - ORDINARY_MAP_FILE_NAME - ((LINEMAPS_LAST_ORDINARY_MAP (pfile->line_table))); + fname = (ORDINARY_MAP_FILE_NAME + ((LINEMAPS_LAST_ORDINARY_MAP (pfile->line_table)))); } return fname; } diff --git a/libcpp/internal.h b/libcpp/internal.h index 97d9bdb..4bafe1c 100644 --- a/libcpp/internal.h +++ b/libcpp/internal.h @@ -123,7 +123,9 @@ enum include_type /* Non-directive including mechanisms. */ IT_CMDLINE, /* -include */ IT_DEFAULT, /* forced header */ - IT_MAIN, /* main */ + IT_MAIN, /* main, start on line 1 */ + IT_MAIN_INJECT, /* main, but there will be an injected preamble + before line 1 */ IT_DIRECTIVE_HWM = IT_IMPORT + 1, /* Directives below this. */ IT_HEADER_HWM = IT_DEFAULT + 1 /* Header files below this. */ @@ -275,7 +277,7 @@ struct lexer_state /* Nonzero to skip evaluating part of an expression. */ unsigned int skip_eval; - /* Nonzero when handling a deferred pragma. */ + /* Nonzero when tokenizing a deferred pragma. */ unsigned char in_deferred_pragma; /* Nonzero if the deferred pragma being handled allows macro expansion. */ @@ -677,10 +679,10 @@ extern void _cpp_init_hashtable (cpp_reader *, cpp_hash_table *); extern void _cpp_destroy_hashtable (cpp_reader *); /* In files.c */ -typedef struct _cpp_file _cpp_file; +enum _cpp_find_file_kind + { _cpp_FFK_NORMAL, _cpp_FFK_FAKE, _cpp_FFK_PRE_INCLUDE, _cpp_FFK_HAS_INCLUDE }; extern _cpp_file *_cpp_find_file (cpp_reader *, const char *, cpp_dir *, - int angle, bool fake, bool preinclude, - bool has_include, location_t); + int angle, _cpp_find_file_kind, location_t); extern bool _cpp_find_failed (_cpp_file *); extern void _cpp_mark_file_once_only (cpp_reader *, struct _cpp_file *); extern void _cpp_fake_include (cpp_reader *, const char *); @@ -747,17 +749,6 @@ extern void _cpp_do_file_change (cpp_reader *, enum lc_reason, const char *, extern void _cpp_pop_buffer (cpp_reader *); extern char *_cpp_bracket_include (cpp_reader *); -/* In directives.c */ -struct _cpp_dir_only_callbacks -{ - /* Called to print a block of lines. */ - void (*print_lines) (int, const void *, size_t); - bool (*maybe_print_line) (location_t); -}; - -extern void _cpp_preprocess_dir_only (cpp_reader *, - const struct _cpp_dir_only_callbacks *); - /* In traditional.c. */ extern bool _cpp_scan_out_logical_line (cpp_reader *, cpp_macro *, bool); extern bool _cpp_read_logical_line_trad (cpp_reader *); diff --git a/libcpp/lex.c b/libcpp/lex.c index 56ac3a1..5d94882 100644 --- a/libcpp/lex.c +++ b/libcpp/lex.c @@ -1372,7 +1372,7 @@ maybe_va_opt_error (cpp_reader *pfile) system headers. */ if (!cpp_in_system_header (pfile)) cpp_error (pfile, CPP_DL_PEDWARN, - "__VA_OPT__ is not available until C++2a"); + "__VA_OPT__ is not available until C++20"); } else if (!pfile->state.va_args_ok) { @@ -1380,7 +1380,7 @@ maybe_va_opt_error (cpp_reader *pfile) variadic macro. */ cpp_error (pfile, CPP_DL_PEDWARN, "__VA_OPT__ can only appear in the expansion" - " of a C++2a variadic macro"); + " of a C++20 variadic macro"); } } @@ -1586,35 +1586,74 @@ create_literal (cpp_reader *pfile, cpp_token *token, const uchar *base, token->val.str.text = dest; } +/* A pair of raw buffer pointers. The currently open one is [1], the + first one is [0]. Used for string literal lexing. */ +struct lit_accum { + _cpp_buff *first; + _cpp_buff *last; + const uchar *rpos; + size_t accum; + + lit_accum () + : first (NULL), last (NULL), rpos (0), accum (0) + { + } + + void append (cpp_reader *, const uchar *, size_t); + + void read_begin (cpp_reader *); + bool reading_p () const + { + return rpos != NULL; + } + char read_char () + { + char c = *rpos++; + if (rpos == BUFF_FRONT (last)) + rpos = NULL; + return c; + } +}; + /* Subroutine of lex_raw_string: Append LEN chars from BASE to the buffer sequence from *FIRST_BUFF_P to LAST_BUFF_P. */ -static void -bufring_append (cpp_reader *pfile, const uchar *base, size_t len, - _cpp_buff **first_buff_p, _cpp_buff **last_buff_p) +void +lit_accum::append (cpp_reader *pfile, const uchar *base, size_t len) { - _cpp_buff *first_buff = *first_buff_p; - _cpp_buff *last_buff = *last_buff_p; - - if (first_buff == NULL) - first_buff = last_buff = _cpp_get_buff (pfile, len); - else if (len > BUFF_ROOM (last_buff)) + if (!last) + /* Starting. */ + first = last = _cpp_get_buff (pfile, len); + else if (len > BUFF_ROOM (last)) { - size_t room = BUFF_ROOM (last_buff); - memcpy (BUFF_FRONT (last_buff), base, room); - BUFF_FRONT (last_buff) += room; + /* There is insufficient room in the buffer. Copy what we can, + and then either extend or create a new one. */ + size_t room = BUFF_ROOM (last); + memcpy (BUFF_FRONT (last), base, room); + BUFF_FRONT (last) += room; base += room; len -= room; - last_buff = _cpp_append_extend_buff (pfile, last_buff, len); - } + accum += room; + + gcc_checking_assert (!rpos); - memcpy (BUFF_FRONT (last_buff), base, len); - BUFF_FRONT (last_buff) += len; + last = _cpp_append_extend_buff (pfile, last, len); + } - *first_buff_p = first_buff; - *last_buff_p = last_buff; + memcpy (BUFF_FRONT (last), base, len); + BUFF_FRONT (last) += len; + accum += len; } +void +lit_accum::read_begin (cpp_reader *pfile) +{ + /* We never accumulate more than 4 chars to read. */ + if (BUFF_ROOM (last) < 4) + + last = _cpp_append_extend_buff (pfile, last, 4); + rpos = BUFF_FRONT (last); +} /* Returns true if a macro has been defined. This might not work if compile with -save-temps, @@ -1657,267 +1696,255 @@ is_macro_not_literal_suffix(cpp_reader *pfile, const uchar *base) return is_macro (pfile, base); } -/* Lexes a raw string. The stored string contains the spelling, including - double quotes, delimiter string, '(' and ')', any leading - 'L', 'u', 'U' or 'u8' and 'R' modifier. It returns the type of the - literal, or CPP_OTHER if it was not properly terminated. +/* Lexes a raw string. The stored string contains the spelling, + including double quotes, delimiter string, '(' and ')', any leading + 'L', 'u', 'U' or 'u8' and 'R' modifier. The created token contains + the type of the literal, or CPP_OTHER if it was not properly + terminated. + + BASE is the start of the token. Updates pfile->buffer->cur to just + after the lexed string. The spelling is NUL-terminated, but it is not guaranteed that this is the first NUL since embedded NULs are preserved. */ static void -lex_raw_string (cpp_reader *pfile, cpp_token *token, const uchar *base, - const uchar *cur) -{ - uchar raw_prefix[17]; - uchar temp_buffer[18]; - const uchar *orig_base; - unsigned int raw_prefix_len = 0, raw_suffix_len = 0; - enum raw_str_phase { RAW_STR_PREFIX, RAW_STR, RAW_STR_SUFFIX }; - raw_str_phase phase = RAW_STR_PREFIX; - enum cpp_ttype type; - size_t total_len = 0; - /* Index into temp_buffer during phases other than RAW_STR, - during RAW_STR phase 17 to tell BUF_APPEND that nothing should - be appended to temp_buffer. */ - size_t temp_buffer_len = 0; - _cpp_buff *first_buff = NULL, *last_buff = NULL; - size_t raw_prefix_start; - _cpp_line_note *note = &pfile->buffer->notes[pfile->buffer->cur_note]; +lex_raw_string (cpp_reader *pfile, cpp_token *token, const uchar *base) +{ + const uchar *pos = base; - type = (*base == 'L' ? CPP_WSTRING : - *base == 'U' ? CPP_STRING32 : - *base == 'u' ? (base[1] == '8' ? CPP_UTF8STRING : CPP_STRING16) - : CPP_STRING); - -#define BUF_APPEND(STR,LEN) \ - do { \ - bufring_append (pfile, (const uchar *)(STR), (LEN), \ - &first_buff, &last_buff); \ - total_len += (LEN); \ - if (__builtin_expect (temp_buffer_len < 17, 0) \ - && (const uchar *)(STR) != base \ - && (LEN) <= 2) \ - { \ - memcpy (temp_buffer + temp_buffer_len, \ - (const uchar *)(STR), (LEN)); \ - temp_buffer_len += (LEN); \ - } \ - } while (0) - - orig_base = base; - ++cur; - raw_prefix_start = cur - base; - for (;;) - { - cppchar_t c; + /* 'tis a pity this information isn't passed down from the lexer's + initial categorization of the token. */ + enum cpp_ttype type = CPP_STRING; - /* If we previously performed any trigraph or line splicing - transformations, undo them in between the opening and closing - double quote. */ - while (note->pos < cur) - ++note; - for (; note->pos == cur; ++note) + if (*pos == 'L') + { + type = CPP_WSTRING; + pos++; + } + else if (*pos == 'U') + { + type = CPP_STRING32; + pos++; + } + else if (*pos == 'u') + { + if (pos[1] == '8') { - switch (note->type) - { - case '\\': - case ' ': - /* Restore backslash followed by newline. */ - BUF_APPEND (base, cur - base); - base = cur; - BUF_APPEND ("\\", 1); - after_backslash: - if (note->type == ' ') - { - /* GNU backslash whitespace newline extension. FIXME - could be any sequence of non-vertical space. When we - can properly restore any such sequence, we should mark - this note as handled so _cpp_process_line_notes - doesn't warn. */ - BUF_APPEND (" ", 1); - } + type = CPP_UTF8STRING; + pos++; + } + else + type = CPP_STRING16; + pos++; + } - BUF_APPEND ("\n", 1); - break; + gcc_checking_assert (pos[0] == 'R' && pos[1] == '"'); + pos += 2; - case 0: - /* Already handled. */ - break; + _cpp_line_note *note = &pfile->buffer->notes[pfile->buffer->cur_note]; - default: - if (_cpp_trigraph_map[note->type]) - { - /* Don't warn about this trigraph in - _cpp_process_line_notes, since trigraphs show up as - trigraphs in raw strings. */ - uchar type = note->type; - note->type = 0; - - if (!CPP_OPTION (pfile, trigraphs)) - /* If we didn't convert the trigraph in the first - place, don't do anything now either. */ - break; + /* Skip notes before the ". */ + while (note->pos < pos) + ++note; - BUF_APPEND (base, cur - base); - base = cur; - BUF_APPEND ("??", 2); + lit_accum accum; + + uchar prefix[17]; + unsigned prefix_len = 0; + enum Phase + { + PHASE_PREFIX = -2, + PHASE_NONE = -1, + PHASE_SUFFIX = 0 + } phase = PHASE_PREFIX; - /* ??/ followed by newline gets two line notes, one for - the trigraph and one for the backslash/newline. */ - if (type == '/' && note[1].pos == cur) - { - if (note[1].type != '\\' - && note[1].type != ' ') - abort (); - BUF_APPEND ("/", 1); - ++note; - goto after_backslash; - } - else - { - /* Skip the replacement character. */ - base = ++cur; - BUF_APPEND (&type, 1); - c = type; - goto check_c; - } - } - else - abort (); - break; - } - } - c = *cur++; - if (__builtin_expect (temp_buffer_len < 17, 0)) - temp_buffer[temp_buffer_len++] = c; + for (;;) + { + gcc_checking_assert (note->pos >= pos); + + /* Undo any escaped newlines and trigraphs. */ + if (!accum.reading_p () && note->pos == pos) + switch (note->type) + { + case '\\': + case ' ': + /* Restore backslash followed by newline. */ + accum.append (pfile, base, pos - base); + base = pos; + accum.read_begin (pfile); + accum.append (pfile, UC"\\", 1); + + after_backslash: + if (note->type == ' ') + /* GNU backslash whitespace newline extension. FIXME + could be any sequence of non-vertical space. When we + can properly restore any such sequence, we should + mark this note as handled so _cpp_process_line_notes + doesn't warn. */ + accum.append (pfile, UC" ", 1); + + accum.append (pfile, UC"\n", 1); + note++; + break; + + case '\n': + /* This can happen for ??/<NEWLINE> when trigraphs are not + being interpretted. */ + gcc_checking_assert (!CPP_OPTION (pfile, trigraphs)); + note->type = 0; + note++; + break; - check_c: - if (phase == RAW_STR_PREFIX) + default: + gcc_checking_assert (_cpp_trigraph_map[note->type]); + + /* Don't warn about this trigraph in + _cpp_process_line_notes, since trigraphs show up as + trigraphs in raw strings. */ + uchar type = note->type; + note->type = 0; + + if (CPP_OPTION (pfile, trigraphs)) + { + accum.append (pfile, base, pos - base); + base = pos; + accum.read_begin (pfile); + accum.append (pfile, UC"??", 2); + accum.append (pfile, &type, 1); + + /* ??/ followed by newline gets two line notes, one for + the trigraph and one for the backslash/newline. */ + if (type == '/' && note[1].pos == pos) + { + note++; + gcc_assert (note->type == '\\' || note->type == ' '); + goto after_backslash; + } + /* Skip the replacement character. */ + base = ++pos; + } + + note++; + break; + } + + /* Now get a char to process. Either from an expanded note, or + from the line buffer. */ + bool read_note = accum.reading_p (); + char c = read_note ? accum.read_char () : *pos++; + + if (phase == PHASE_PREFIX) { - while (raw_prefix_len < temp_buffer_len) + if (c == '(') { - raw_prefix[raw_prefix_len] = temp_buffer[raw_prefix_len]; - switch (raw_prefix[raw_prefix_len]) - { - case ' ': case '(': case ')': case '\\': case '\t': - case '\v': case '\f': case '\n': default: - break; - /* Basic source charset except the above chars. */ - case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': - case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': - case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': - case 's': case 't': case 'u': case 'v': case 'w': case 'x': - case 'y': case 'z': - case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': - case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': - case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': - case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': - case 'Y': case 'Z': - case '0': case '1': case '2': case '3': case '4': case '5': - case '6': case '7': case '8': case '9': - case '_': case '{': case '}': case '#': case '[': case ']': - case '<': case '>': case '%': case ':': case ';': case '.': - case '?': case '*': case '+': case '-': case '/': case '^': - case '&': case '|': case '~': case '!': case '=': case ',': - case '"': case '\'': - if (raw_prefix_len < 16) - { - raw_prefix_len++; - continue; - } - break; - } - - if (raw_prefix[raw_prefix_len] != '(') - { - int col = CPP_BUF_COLUMN (pfile->buffer, cur) + 1; - if (raw_prefix_len == 16) - cpp_error_with_line (pfile, CPP_DL_ERROR, token->src_loc, - col, "raw string delimiter longer " - "than 16 characters"); - else if (raw_prefix[raw_prefix_len] == '\n') - cpp_error_with_line (pfile, CPP_DL_ERROR, token->src_loc, - col, "invalid new-line in raw " - "string delimiter"); - else - cpp_error_with_line (pfile, CPP_DL_ERROR, token->src_loc, - col, "invalid character '%c' in " - "raw string delimiter", - (int) raw_prefix[raw_prefix_len]); - pfile->buffer->cur = orig_base + raw_prefix_start - 1; - create_literal (pfile, token, orig_base, - raw_prefix_start - 1, CPP_OTHER); - if (first_buff) - _cpp_release_buff (pfile, first_buff); - return; - } - raw_prefix[raw_prefix_len] = '"'; - phase = RAW_STR; - /* Nothing should be appended to temp_buffer during - RAW_STR phase. */ - temp_buffer_len = 17; - break; + /* Done. */ + phase = PHASE_NONE; + prefix[prefix_len++] = '"'; + } + else if (prefix_len < 16 + /* Prefix chars are any of the basic character set, + [lex.charset] except for ' + ()\\\t\v\f\n'. Optimized for a contiguous + alphabet. */ + /* Unlike a switch, this collapses down to one or + two shift and bitmask operations on an ASCII + system, with an outlier or two. */ + && (('Z' - 'A' == 25 + ? ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) + : ISIDST (c)) + || (c >= '0' && c <= '9') + || c == '_' || c == '{' || c == '}' + || c == '[' || c == ']' || c == '#' + || c == '<' || c == '>' || c == '%' + || c == ':' || c == ';' || c == '.' || c == '?' + || c == '*' || c == '+' || c == '-' || c == '/' + || c == '^' || c == '&' || c == '|' || c == '~' + || c == '!' || c == '=' || c == ',' + || c == '"' || c == '\'')) + prefix[prefix_len++] = c; + else + { + /* Something is wrong. */ + int col = CPP_BUF_COLUMN (pfile->buffer, pos) + read_note; + if (prefix_len == 16) + cpp_error_with_line (pfile, CPP_DL_ERROR, token->src_loc, + col, "raw string delimiter longer " + "than 16 characters"); + else if (c == '\n') + cpp_error_with_line (pfile, CPP_DL_ERROR, token->src_loc, + col, "invalid new-line in raw " + "string delimiter"); + else + cpp_error_with_line (pfile, CPP_DL_ERROR, token->src_loc, + col, "invalid character '%c' in " + "raw string delimiter", c); + type = CPP_OTHER; + phase = PHASE_NONE; + /* Continue until we get a close quote, that's probably + the best failure mode. */ + prefix_len = 0; } continue; } - else if (phase == RAW_STR_SUFFIX) + + if (phase != PHASE_NONE) { - while (raw_suffix_len <= raw_prefix_len - && raw_suffix_len < temp_buffer_len - && temp_buffer[raw_suffix_len] == raw_prefix[raw_suffix_len]) - raw_suffix_len++; - if (raw_suffix_len > raw_prefix_len) + if (prefix[phase] != c) + phase = PHASE_NONE; + else if (unsigned (phase + 1) == prefix_len) break; - if (raw_suffix_len == temp_buffer_len) - continue; - phase = RAW_STR; - /* Nothing should be appended to temp_buffer during - RAW_STR phase. */ - temp_buffer_len = 17; - } - if (c == ')') - { - phase = RAW_STR_SUFFIX; - raw_suffix_len = 0; - temp_buffer_len = 0; + else + { + phase = Phase (phase + 1); + continue; + } } - else if (c == '\n') + + if (!prefix_len && c == '"') + /* Failure mode lexing. */ + goto out; + else if (prefix_len && c == ')') + phase = PHASE_SUFFIX; + else if (!read_note && c == '\n') { + pos--; + pfile->buffer->cur = pos; if (pfile->state.in_directive || (pfile->state.parsing_args && pfile->buffer->next_line >= pfile->buffer->rlimit)) { - cur--; - type = CPP_OTHER; cpp_error_with_line (pfile, CPP_DL_ERROR, token->src_loc, 0, "unterminated raw string"); - break; + type = CPP_OTHER; + goto out; } - BUF_APPEND (base, cur - base); + accum.append (pfile, base, pos - base + 1); + _cpp_process_line_notes (pfile, false); - if (pfile->buffer->cur < pfile->buffer->rlimit) + if (pfile->buffer->next_line < pfile->buffer->rlimit) CPP_INCREMENT_LINE (pfile, 0); pfile->buffer->need_line = true; - pfile->buffer->cur = cur-1; - _cpp_process_line_notes (pfile, false); if (!_cpp_get_fresh_line (pfile)) { + /* We ran out of file and failed to get a line. */ location_t src_loc = token->src_loc; token->type = CPP_EOF; /* Tell the compiler the line number of the EOF token. */ token->src_loc = pfile->line_table->highest_line; token->flags = BOL; - if (first_buff != NULL) - _cpp_release_buff (pfile, first_buff); + if (accum.first) + _cpp_release_buff (pfile, accum.first); cpp_error_with_line (pfile, CPP_DL_ERROR, src_loc, 0, "unterminated raw string"); + /* Now pop the buffer that _cpp_get_fresh_line did not. */ + _cpp_pop_buffer (pfile); return; } - cur = base = pfile->buffer->cur; + pos = base = pfile->buffer->cur; note = &pfile->buffer->notes[pfile->buffer->cur_note]; } } @@ -1927,7 +1954,7 @@ lex_raw_string (cpp_reader *pfile, cpp_token *token, const uchar *base, /* If a string format macro, say from inttypes.h, is placed touching a string literal it could be parsed as a C++11 user-defined string literal thus breaking the program. */ - if (is_macro_not_literal_suffix (pfile, cur)) + if (is_macro_not_literal_suffix (pfile, pos)) { /* Raise a warning, but do not consume subsequent tokens. */ if (CPP_OPTION (pfile, warn_literal_suffix) && !pfile->state.skipping) @@ -1937,37 +1964,37 @@ lex_raw_string (cpp_reader *pfile, cpp_token *token, const uchar *base, "a space between literal and string macro"); } /* Grab user defined literal suffix. */ - else if (ISIDST (*cur)) + else if (ISIDST (*pos)) { type = cpp_userdef_string_add_type (type); - ++cur; + ++pos; - while (ISIDNUM (*cur)) - ++cur; + while (ISIDNUM (*pos)) + ++pos; } } - pfile->buffer->cur = cur; - if (first_buff == NULL) - create_literal (pfile, token, base, cur - base, type); + out: + pfile->buffer->cur = pos; + if (!accum.accum) + create_literal (pfile, token, base, pos - base, type); else { - uchar *dest = _cpp_unaligned_alloc (pfile, total_len + (cur - base) + 1); + size_t extra_len = pos - base; + uchar *dest = _cpp_unaligned_alloc (pfile, accum.accum + extra_len + 1); token->type = type; - token->val.str.len = total_len + (cur - base); + token->val.str.len = accum.accum + extra_len; token->val.str.text = dest; - last_buff = first_buff; - while (last_buff != NULL) + for (_cpp_buff *buf = accum.first; buf; buf = buf->next) { - memcpy (dest, last_buff->base, - BUFF_FRONT (last_buff) - last_buff->base); - dest += BUFF_FRONT (last_buff) - last_buff->base; - last_buff = last_buff->next; + size_t len = BUFF_FRONT (buf) - buf->base; + memcpy (dest, buf->base, len); + dest += len; } - _cpp_release_buff (pfile, first_buff); - memcpy (dest, base, cur - base); - dest[cur - base] = '\0'; + _cpp_release_buff (pfile, accum.first); + memcpy (dest, base, extra_len); + dest[extra_len] = '\0'; } } @@ -2000,7 +2027,7 @@ lex_string (cpp_reader *pfile, cpp_token *token, const uchar *base) } if (terminator == 'R') { - lex_raw_string (pfile, token, base, cur); + lex_raw_string (pfile, token, base); return; } if (terminator == '"') @@ -2651,8 +2678,6 @@ _cpp_lex_token (cpp_reader *pfile) bool _cpp_get_fresh_line (cpp_reader *pfile) { - int return_at_eof; - /* We can't get a new line until we leave the current directive. */ if (pfile->state.in_directive) return false; @@ -2683,10 +2708,17 @@ _cpp_get_fresh_line (cpp_reader *pfile) buffer->next_line = buffer->rlimit; } - return_at_eof = buffer->return_at_eof; - _cpp_pop_buffer (pfile); - if (pfile->buffer == NULL || return_at_eof) - return false; + if (buffer->prev && !buffer->return_at_eof) + _cpp_pop_buffer (pfile); + else + { + /* End of translation. Do not pop the buffer yet. Increment + line number so that the EOF token is on a line of its own + (_cpp_lex_direct doesn't increment in that case, because + it's hard for it to distinguish this special case). */ + CPP_INCREMENT_LINE (pfile, 0); + return false; + } } } @@ -2740,6 +2772,8 @@ _cpp_lex_direct (cpp_reader *pfile) /* Tell the compiler the line number of the EOF token. */ result->src_loc = pfile->line_table->highest_line; result->flags = BOL; + /* Now pop the buffer that _cpp_get_fresh_line did not. */ + _cpp_pop_buffer (pfile); } return result; } @@ -2984,7 +3018,7 @@ _cpp_lex_direct (cpp_reader *pfile) buffer->cur++, result->type = CPP_LESS_EQ; if (*buffer->cur == '>' && CPP_OPTION (pfile, cplusplus) - && CPP_OPTION (pfile, lang) >= CLK_GNUCXX2A) + && CPP_OPTION (pfile, lang) >= CLK_GNUCXX20) buffer->cur++, result->type = CPP_SPACESHIP; } else if (*buffer->cur == '<') @@ -3826,3 +3860,486 @@ cpp_stop_forcing_token_locations (cpp_reader *r) { r->forced_token_location = 0; } + +/* We're looking at \, if it's escaping EOL, look past it. If at + LIMIT, don't advance. */ + +static const unsigned char * +do_peek_backslash (const unsigned char *peek, const unsigned char *limit) +{ + const unsigned char *probe = peek; + + if (__builtin_expect (peek[1] == '\n', true)) + { + eol: + probe += 2; + if (__builtin_expect (probe < limit, true)) + { + peek = probe; + if (*peek == '\\') + /* The user might be perverse. */ + return do_peek_backslash (peek, limit); + } + } + else if (__builtin_expect (peek[1] == '\r', false)) + { + if (probe[2] == '\n') + probe++; + goto eol; + } + + return peek; +} + +static const unsigned char * +do_peek_next (const unsigned char *peek, const unsigned char *limit) +{ + if (__builtin_expect (*peek == '\\', false)) + peek = do_peek_backslash (peek, limit); + return peek; +} + +static const unsigned char * +do_peek_prev (const unsigned char *peek, const unsigned char *bound) +{ + if (peek == bound) + return NULL; + + unsigned char c = *--peek; + if (__builtin_expect (c == '\n', false) + || __builtin_expect (c == 'r', false)) + { + if (peek == bound) + return peek; + int ix = -1; + if (c == '\n' && peek[ix] == '\r') + { + if (peek + ix == bound) + return peek; + ix--; + } + + if (peek[ix] == '\\') + return do_peek_prev (peek + ix, bound); + + return peek; + } + else + return peek; +} + +/* Directives-only scanning. Somewhat more relaxed than correct + parsing -- some ill-formed programs will not be rejected. */ + +void +cpp_directive_only_process (cpp_reader *pfile, + void *data, + void (*cb) (cpp_reader *, CPP_DO_task, void *, ...)) +{ + do + { + restart: + /* Buffer initialization, but no line cleaning. */ + cpp_buffer *buffer = pfile->buffer; + buffer->cur_note = buffer->notes_used = 0; + buffer->cur = buffer->line_base = buffer->next_line; + buffer->need_line = false; + /* Files always end in a newline. We rely on this for + character peeking safety. */ + gcc_assert (buffer->rlimit[-1] == '\n'); + + const unsigned char *base = buffer->cur; + unsigned line_count = 0; + const unsigned char *line_start = base; + + bool bol = true; + bool raw = false; + + const unsigned char *lwm = base; + for (const unsigned char *pos = base, *limit = buffer->rlimit; + pos < limit;) + { + unsigned char c = *pos++; + /* This matches the switch in _cpp_lex_direct. */ + switch (c) + { + case ' ': case '\t': case '\f': case '\v': + /* Whitespace, do nothing. */ + break; + + case '\r': /* MAC line ending, or Windows \r\n */ + if (*pos == '\n') + pos++; + /* FALLTHROUGH */ + + case '\n': + bol = true; + + next_line: + CPP_INCREMENT_LINE (pfile, 0); + line_count++; + line_start = pos; + break; + + case '\\': + /* <backslash><newline> is removed, and doesn't undo any + preceeding escape or whatnot. */ + if (*pos == '\n') + { + pos++; + goto next_line; + } + else if (*pos == '\r') + { + if (pos[1] == '\n') + pos++; + pos++; + goto next_line; + } + goto dflt; + + case '#': + if (bol) + { + /* Line directive. */ + if (pos - 1 > base && !pfile->state.skipping) + cb (pfile, CPP_DO_print, data, + line_count, base, pos - 1 - base); + + /* Prep things for directive handling. */ + buffer->next_line = pos; + buffer->need_line = true; + bool ok = _cpp_get_fresh_line (pfile); + gcc_checking_assert (ok); + + /* Ensure proper column numbering for generated + error messages. */ + buffer->line_base -= pos - line_start; + + _cpp_handle_directive (pfile, line_start + 1 != pos); + + /* Sanitize the line settings. Duplicate #include's can + mess things up. */ + // FIXME: Necessary? + pfile->line_table->highest_location + = pfile->line_table->highest_line; + + if (!pfile->state.skipping + && pfile->buffer->next_line < pfile->buffer->rlimit) + cb (pfile, CPP_DO_location, data, + pfile->line_table->highest_line); + + goto restart; + } + goto dflt; + + case '/': + { + const unsigned char *peek = do_peek_next (pos, limit); + if (!(*peek == '/' || *peek == '*')) + goto dflt; + + /* Line or block comment */ + bool is_block = *peek == '*'; + bool star = false; + bool esc = false; + location_t sloc + = linemap_position_for_column (pfile->line_table, + pos - line_start); + + while (pos < limit) + { + char c = *pos++; + switch (c) + { + case '\\': + esc = true; + break; + + case '\r': + if (*pos == '\n') + pos++; + /* FALLTHROUGH */ + + case '\n': + { + CPP_INCREMENT_LINE (pfile, 0); + line_count++; + line_start = pos; + if (!esc && !is_block) + { + bol = true; + goto done_comment; + } + } + if (!esc) + star = false; + esc = false; + break; + + case '*': + if (pos > peek && !esc) + star = is_block; + esc = false; + break; + + case '/': + if (star) + goto done_comment; + /* FALLTHROUGH */ + + default: + star = false; + esc = false; + break; + } + } + cpp_error_with_line (pfile, CPP_DL_ERROR, sloc, 0, + "unterminated comment"); + done_comment: + lwm = pos; + break; + } + + case '\'': + if (!CPP_OPTION (pfile, digit_separators)) + goto delimited_string; + + /* Possibly a number punctuator. */ + if (!ISIDNUM (*do_peek_next (pos, limit))) + goto delimited_string; + + goto quote_peek; + + case '\"': + if (!CPP_OPTION (pfile, rliterals)) + goto delimited_string; + + quote_peek: + { + /* For ' see if it's a number punctuator + \.?<digit>(<digit>|<identifier-nondigit> + |'<digit>|'<nondigit>|[eEpP]<sign>|\.)* */ + /* For " see if it's a raw string + {U,L,u,u8}R. This includes CPP_NUMBER detection, + because that could be 0e+R. */ + const unsigned char *peek = pos - 1; + bool quote_first = c == '"'; + bool quote_eight = false; + bool maybe_number_start = false; + bool want_number = false; + + while ((peek = do_peek_prev (peek, lwm))) + { + unsigned char p = *peek; + if (quote_first) + { + if (!raw) + { + if (p != 'R') + break; + raw = true; + continue; + } + + quote_first = false; + if (p == 'L' || p == 'U' || p == 'u') + ; + else if (p == '8') + quote_eight = true; + else + goto second_raw; + } + else if (quote_eight) + { + if (p != 'u') + { + raw = false; + break; + } + quote_eight = false; + } + else if (c == '"') + { + second_raw:; + if (!want_number && ISIDNUM (p)) + { + raw = false; + break; + } + } + + if (ISDIGIT (p)) + maybe_number_start = true; + else if (p == '.') + want_number = true; + else if (ISIDNUM (p)) + maybe_number_start = false; + else if (p == '+' || p == '-') + { + if (const unsigned char *peek_prev + = do_peek_prev (peek, lwm)) + { + p = *peek_prev; + if (p == 'e' || p == 'E' + || p == 'p' || p == 'P') + { + want_number = true; + maybe_number_start = false; + } + else + break; + } + else + break; + } + else if (p == '\'' || p == '\"') + { + /* If this is lwm, this must be the end of a + previous string. So this is a trailing + literal type, (a) if those are allowed, + and (b) maybe_start is false. Otherwise + this must be a CPP_NUMBER because we've + met another ', and we'd have checked that + in its own right. */ + if (peek == lwm && CPP_OPTION (pfile, uliterals)) + { + if (!maybe_number_start && !want_number) + /* Must be a literal type. */ + raw = false; + } + else if (p == '\'' + && CPP_OPTION (pfile, digit_separators)) + maybe_number_start = true; + break; + } + else if (c == '\'') + break; + else if (!quote_first && !quote_eight) + break; + } + + if (maybe_number_start) + { + if (c == '\'') + /* A CPP NUMBER. */ + goto dflt; + raw = false; + } + + goto delimited_string; + } + + delimited_string: + { + /* (Possibly raw) string or char literal. */ + unsigned char end = c; + int delim_len = -1; + const unsigned char *delim = NULL; + location_t sloc = linemap_position_for_column (pfile->line_table, + pos - line_start); + int esc = 0; + + if (raw) + { + /* There can be no line breaks in the delimiter. */ + delim = pos; + for (delim_len = 0; (c = *pos++) != '('; delim_len++) + { + if (delim_len == 16) + { + cpp_error_with_line (pfile, CPP_DL_ERROR, + sloc, 0, + "raw string delimiter" + " longer than %d" + " characters", + delim_len); + raw = false; + pos = delim; + break; + } + if (strchr (") \\\t\v\f\n", c)) + { + cpp_error_with_line (pfile, CPP_DL_ERROR, + sloc, 0, + "invalid character '%c'" + " in raw string" + " delimiter", c); + raw = false; + pos = delim; + break; + } + if (pos >= limit) + goto bad_string; + } + } + + while (pos < limit) + { + char c = *pos++; + switch (c) + { + case '\\': + if (!raw) + esc++; + break; + + case '\r': + if (*pos == '\n') + pos++; + /* FALLTHROUGH */ + + case '\n': + { + CPP_INCREMENT_LINE (pfile, 0); + line_count++; + line_start = pos; + } + if (esc) + esc--; + break; + + case ')': + if (raw + && pos + delim_len + 1 < limit + && pos[delim_len] == end + && !memcmp (delim, pos, delim_len)) + { + pos += delim_len + 1; + raw = false; + goto done_string; + } + break; + + default: + if (!raw && !(esc & 1) && c == end) + goto done_string; + esc = 0; + break; + } + } + bad_string: + cpp_error_with_line (pfile, CPP_DL_ERROR, sloc, 0, + "unterminated literal"); + + done_string: + raw = false; + lwm = pos - 1; + } + goto dflt; + + default: + dflt: + bol = false; + pfile->mi_valid = false; + break; + } + } + + if (buffer->rlimit > base && !pfile->state.skipping) + cb (pfile, CPP_DO_print, data, line_count, base, buffer->rlimit - base); + + _cpp_pop_buffer (pfile); + } + while (pfile->buffer); +} diff --git a/libcpp/macro.c b/libcpp/macro.c index 2573f31..2c7d732 100644 --- a/libcpp/macro.c +++ b/libcpp/macro.c @@ -1035,7 +1035,7 @@ _cpp_arguments_ok (cpp_reader *pfile, cpp_macro *macro, const cpp_hashnode *node if (argc < macro->paramc) { - /* In C++2a (here the va_opt flag is used), and also as a GNU + /* In C++20 (here the va_opt flag is used), and also as a GNU extension, variadic arguments are allowed to not appear in the invocation at all. e.g. #define debug(format, args...) something @@ -1258,11 +1258,13 @@ collect_args (cpp_reader *pfile, const cpp_hashnode *node, if (token->type == CPP_EOF) { - /* We still need the CPP_EOF to end directives, and to end - pre-expansion of a macro argument. Step back is not - unconditional, since we don't want to return a CPP_EOF to our - callers at the end of an -include-d file. */ - if (pfile->context->prev || pfile->state.in_directive) + /* We still need the CPP_EOF to end directives, to end + pre-expansion of a macro argument, and at the end of the main + file. We do not want it at the end of a -include'd (forced) + header file. */ + if (pfile->state.in_directive + || !pfile->line_table->depth + || pfile->context->prev) _cpp_backup_tokens (pfile, 1); cpp_error (pfile, CPP_DL_ERROR, "unterminated argument list invoking macro \"%s\"", @@ -2870,8 +2872,7 @@ cpp_get_token_1 (cpp_reader *pfile, location_t *location) || (peek_tok->flags & PREV_WHITE)); node = pfile->cb.macro_to_expand (pfile, result); if (node) - ret = enter_macro_context (pfile, node, result, - virt_loc); + ret = enter_macro_context (pfile, node, result, virt_loc); else if (whitespace_after) { /* If macro_to_expand hook returned NULL and it @@ -2888,8 +2889,7 @@ cpp_get_token_1 (cpp_reader *pfile, location_t *location) } } else - ret = enter_macro_context (pfile, node, result, - virt_loc); + ret = enter_macro_context (pfile, node, result, virt_loc); if (ret) { if (pfile->state.in_directive || ret == 2) diff --git a/libcpp/po/ChangeLog b/libcpp/po/ChangeLog index 604430d..6241652 100644 --- a/libcpp/po/ChangeLog +++ b/libcpp/po/ChangeLog @@ -1,3 +1,7 @@ +2020-05-15 Joseph Myers <joseph@codesourcery.com> + + * sv.po: Update. + 2020-04-06 Joseph Myers <joseph@codesourcery.com> * eo.po: Update. diff --git a/libcpp/po/sv.po b/libcpp/po/sv.po index d26840b..b55e11e 100644 --- a/libcpp/po/sv.po +++ b/libcpp/po/sv.po @@ -11,9 +11,9 @@ msgstr "" "Project-Id-Version: cpplib 10.1-b20200209\n" "Report-Msgid-Bugs-To: https://gcc.gnu.org/bugs/\n" "POT-Creation-Date: 2020-02-07 22:33+0000\n" -"PO-Revision-Date: 2020-02-16 13:12+0100\n" +"PO-Revision-Date: 2020-05-15 15:50+0200\n" "Last-Translator: Göran Uddeborg <goeran@uddeborg.se>\n" -"Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n" +"Language-Team: Swedish <tp-sv-list@lists.sourceforge.net>\n" "Language: sv\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -796,7 +796,7 @@ msgstr "”(” saknas före operanden till ”%s”" #: macro.c:389 #, c-format msgid "operator \"%s\" requires a header-name" -msgstr "operatorn ”%s” måste ha en huvudnamn" +msgstr "operatorn ”%s” måste ha ett huvudnamn" #: macro.c:406 #, c-format diff --git a/libcpp/system.h b/libcpp/system.h index 37fc262..0a0629d 100644 --- a/libcpp/system.h +++ b/libcpp/system.h @@ -422,26 +422,6 @@ extern void fancy_abort (const char *, int, const char *) ATTRIBUTE_NORETURN; #define gcc_checking_assert(EXPR) ((void)(0 && (EXPR))) #endif -/* Provide a fake boolean type. We make no attempt to use the - C99 _Bool, as it may not be available in the bootstrap compiler, - and even if it is, it is liable to be buggy. - This must be after all inclusion of system headers, as some of - them will mess us up. */ -#undef bool -#undef true -#undef false -#undef TRUE -#undef FALSE - -#ifndef __cplusplus -#define bool unsigned char -#endif -#define true 1 -#define false 0 - -/* Some compilers do not allow the use of unsigned char in bitfields. */ -#define BOOL_BITFIELD unsigned int - /* Poison identifiers we do not want to use. */ #if (GCC_VERSION >= 3000) #undef calloc diff --git a/libcpp/traditional.c b/libcpp/traditional.c index 039fcfe..77adb3b 100644 --- a/libcpp/traditional.c +++ b/libcpp/traditional.c @@ -312,7 +312,11 @@ _cpp_read_logical_line_trad (cpp_reader *pfile) do { if (pfile->buffer->need_line && !_cpp_get_fresh_line (pfile)) - return false; + { + /* Now pop the buffer that _cpp_get_fresh_line did not. */ + _cpp_pop_buffer (pfile); + return false; + } } while (!_cpp_scan_out_logical_line (pfile, NULL, false) || pfile->state.skipping); |