aboutsummaryrefslogtreecommitdiff
path: root/libcpp
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2020-07-11 12:43:49 -0700
committerIan Lance Taylor <iant@golang.org>2020-07-11 12:43:49 -0700
commit4854d721be78358e59367982bdd94461b4be3c5a (patch)
tree8ead189e618f8ef1456c8b02c81de0cc1585d8a6 /libcpp
parent3cdc95b9f8d6c90c4a279783fd3da961c5afb22c (diff)
parente109f6e438b72ef3e403162971068d28d09b82f5 (diff)
downloadgcc-4854d721be78358e59367982bdd94461b4be3c5a.zip
gcc-4854d721be78358e59367982bdd94461b4be3c5a.tar.gz
gcc-4854d721be78358e59367982bdd94461b4be3c5a.tar.bz2
Merge from trunk revision e109f6e438b72ef3e403162971068d28d09b82f5
Diffstat (limited to 'libcpp')
-rw-r--r--libcpp/ChangeLog100
-rw-r--r--libcpp/Makefile.in12
-rw-r--r--libcpp/aclocal.m42
-rw-r--r--libcpp/charset.c2
-rwxr-xr-xlibcpp/configure277
-rw-r--r--libcpp/configure.ac12
-rw-r--r--libcpp/directives-only.c240
-rw-r--r--libcpp/directives.c44
-rw-r--r--libcpp/files.c66
-rw-r--r--libcpp/include/cpplib.h25
-rw-r--r--libcpp/include/line-map.h11
-rw-r--r--libcpp/init.c28
-rw-r--r--libcpp/internal.h23
-rw-r--r--libcpp/lex.c1039
-rw-r--r--libcpp/macro.c20
-rw-r--r--libcpp/po/ChangeLog4
-rw-r--r--libcpp/po/sv.po6
-rw-r--r--libcpp/system.h20
-rw-r--r--libcpp/traditional.c6
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);