/* CPP Library.
- Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008,
- 2009 Free Software Foundation, Inc.
+ Copyright (C) 1986-2020 Free Software Foundation, Inc.
Contributed by Per Bothner, 1994-95.
Based on CCCP program by Paul Rubin, June 1986
Adapted to ANSI C, Richard Stallman, Jan 1987
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 2, or (at your option) any
+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,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+along with this program; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
#include "internal.h"
#include "mkdeps.h"
#include "localedir.h"
+#include "filenames.h"
+
+#ifndef ENABLE_CANONICAL_SYSTEM_HEADERS
+#ifdef HAVE_DOS_BASED_FILE_SYSTEM
+#define ENABLE_CANONICAL_SYSTEM_HEADERS 1
+#else
+#define ENABLE_CANONICAL_SYSTEM_HEADERS 0
+#endif
+#endif
static void init_library (void);
-static void mark_named_operators (cpp_reader *);
+static void mark_named_operators (cpp_reader *, int);
static void read_original_filename (cpp_reader *);
static void read_original_directory (cpp_reader *);
static void post_options (cpp_reader *);
char cplusplus;
char extended_numbers;
char extended_identifiers;
+ char c11_identifiers;
char std;
- char cplusplus_comments;
char digraphs;
char uliterals;
+ char rliterals;
+ char user_literals;
+ char binary_constants;
+ char digit_separators;
+ char trigraphs;
+ char utf8_char_literals;
+ char va_opt;
+ char scope;
+ char dfp_constants;
};
static const struct lang_flags lang_defaults[] =
-{ /* c99 c++ xnum xid std // digr ulit */
- /* GNUC89 */ { 0, 0, 1, 0, 0, 1, 1, 0 },
- /* GNUC99 */ { 1, 0, 1, 0, 0, 1, 1, 1 },
- /* STDC89 */ { 0, 0, 0, 0, 1, 0, 0, 0 },
- /* STDC94 */ { 0, 0, 0, 0, 1, 0, 1, 0 },
- /* STDC99 */ { 1, 0, 1, 0, 1, 1, 1, 0 },
- /* GNUCXX */ { 0, 1, 1, 0, 0, 1, 1, 0 },
- /* CXX98 */ { 0, 1, 1, 0, 1, 1, 1, 0 },
- /* GNUCXX0X */ { 1, 1, 1, 0, 0, 1, 1, 1 },
- /* CXX0X */ { 1, 1, 1, 0, 1, 1, 1, 1 },
- /* ASM */ { 0, 0, 1, 0, 0, 1, 0, 0 }
- /* xid should be 1 for GNUC99, STDC99, GNUCXX, CXX98, GNUCXX0X, and
- CXX0X when no longer experimental (when all uses of identifiers
- in the compiler have been audited for correct handling of
- extended identifiers). */
+{ /* c99 c++ xnum xid c11 std digr ulit rlit udlit bincst digsep trig u8chlit vaopt scope dfp */
+ /* GNUC89 */ { 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0 },
+ /* GNUC99 */ { 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0 },
+ /* GNUC11 */ { 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0 },
+ /* GNUC17 */ { 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0 },
+ /* GNUC2X */ { 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1 },
+ /* STDC89 */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 },
+ /* STDC94 */ { 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 },
+ /* STDC99 */ { 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 },
+ /* STDC11 */ { 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0 },
+ /* STDC17 */ { 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0 },
+ /* STDC2X */ { 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1 },
+ /* GNUCXX */ { 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0 },
+ /* CXX98 */ { 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0 },
+ /* GNUCXX11 */ { 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0 },
+ /* CXX11 */ { 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0 },
+ /* GNUCXX14 */ { 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0 },
+ /* 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 },
+ /* ASM */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};
/* Sets internal flags correctly for a given language. */
CPP_OPTION (pfile, cplusplus) = l->cplusplus;
CPP_OPTION (pfile, extended_numbers) = l->extended_numbers;
CPP_OPTION (pfile, extended_identifiers) = l->extended_identifiers;
+ CPP_OPTION (pfile, c11_identifiers) = l->c11_identifiers;
CPP_OPTION (pfile, std) = l->std;
- CPP_OPTION (pfile, trigraphs) = l->std;
- CPP_OPTION (pfile, cplusplus_comments) = l->cplusplus_comments;
CPP_OPTION (pfile, digraphs) = l->digraphs;
CPP_OPTION (pfile, uliterals) = l->uliterals;
+ CPP_OPTION (pfile, rliterals) = l->rliterals;
+ CPP_OPTION (pfile, user_literals) = l->user_literals;
+ CPP_OPTION (pfile, binary_constants) = l->binary_constants;
+ CPP_OPTION (pfile, digit_separators) = l->digit_separators;
+ CPP_OPTION (pfile, trigraphs) = l->trigraphs;
+ CPP_OPTION (pfile, utf8_char_literals) = l->utf8_char_literals;
+ CPP_OPTION (pfile, va_opt) = l->va_opt;
+ CPP_OPTION (pfile, scope) = l->scope;
+ CPP_OPTION (pfile, dfp_constants) = l->dfp_constants;
}
/* Initialize library global state. */
{
initialized = 1;
+ _cpp_init_lexer ();
+
/* Set up the trigraph map. This doesn't need to do anything if
we were compiled with a compiler that supports C99 designated
initializers. */
/* Initialize a cpp_reader structure. */
cpp_reader *
-cpp_create_reader (enum c_lang lang, hash_table *table,
- struct line_maps *line_table)
+cpp_create_reader (enum c_lang lang, cpp_hash_table *table,
+ class line_maps *line_table)
{
cpp_reader *pfile;
init_library ();
pfile = XCNEW (cpp_reader);
+ memset (&pfile->base_context, 0, sizeof (pfile->base_context));
cpp_set_lang (pfile, lang);
CPP_OPTION (pfile, warn_multichar) = 1;
CPP_OPTION (pfile, discard_comments) = 1;
CPP_OPTION (pfile, discard_comments_in_macro_exp) = 1;
- CPP_OPTION (pfile, show_column) = 1;
+ CPP_OPTION (pfile, max_include_depth) = 200;
CPP_OPTION (pfile, tabstop) = 8;
CPP_OPTION (pfile, operator_names) = 1;
CPP_OPTION (pfile, warn_trigraphs) = 2;
CPP_OPTION (pfile, warn_endif_labels) = 1;
- CPP_OPTION (pfile, warn_deprecated) = 1;
- CPP_OPTION (pfile, warn_long_long) = !CPP_OPTION (pfile, c99);
+ CPP_OPTION (pfile, cpp_warn_c90_c99_compat) = -1;
+ CPP_OPTION (pfile, cpp_warn_c11_c2x_compat) = -1;
+ CPP_OPTION (pfile, cpp_warn_cxx11_compat) = 0;
+ CPP_OPTION (pfile, cpp_warn_deprecated) = 1;
+ CPP_OPTION (pfile, cpp_warn_long_long) = 0;
CPP_OPTION (pfile, dollars_in_ident) = 1;
CPP_OPTION (pfile, warn_dollars) = 1;
CPP_OPTION (pfile, warn_variadic_macros) = 1;
CPP_OPTION (pfile, warn_builtin_macro_redefined) = 1;
+ CPP_OPTION (pfile, cpp_warn_implicit_fallthrough) = 0;
+ /* By default, track locations of tokens resulting from macro
+ expansion. The '2' means, track the locations with the highest
+ accuracy. Read the comments for struct
+ cpp_options::track_macro_expansion to learn about the other
+ values. */
+ CPP_OPTION (pfile, track_macro_expansion) = 2;
CPP_OPTION (pfile, warn_normalize) = normalized_C;
+ CPP_OPTION (pfile, warn_literal_suffix) = 1;
+ CPP_OPTION (pfile, canonical_system_headers)
+ = ENABLE_CANONICAL_SYSTEM_HEADERS;
+ CPP_OPTION (pfile, ext_numeric_literals) = 1;
+ CPP_OPTION (pfile, warn_date_time) = 0;
/* Default CPP arithmetic to something sensible for the host for the
benefit of dumb users like fix-header. */
/* Initialize the base context. */
pfile->context = &pfile->base_context;
- pfile->base_context.macro = 0;
+ pfile->base_context.c.macro = 0;
pfile->base_context.prev = pfile->base_context.next = 0;
/* Aligned and unaligned storage. */
pfile->a_buff = _cpp_get_buff (pfile, 0);
pfile->u_buff = _cpp_get_buff (pfile, 0);
+ /* Initialize table for push_macro/pop_macro. */
+ pfile->pushed_macros = 0;
+
+ /* Do not force token locations by default. */
+ pfile->forced_token_location = 0;
+
+ /* Initialize source_date_epoch to -2 (not yet set). */
+ pfile->source_date_epoch = (time_t) -2;
+
/* The expression parser stack. */
_cpp_expand_op_stack (pfile);
/* Initialize the buffer obstack. */
- _obstack_begin (&pfile->buffer_ob, 0, 0,
- (void *(*) (long)) xmalloc,
- (void (*) (void *)) free);
+ obstack_specify_allocation (&pfile->buffer_ob, 0, 0, xmalloc, free);
_cpp_init_files (pfile);
/* Set the line_table entry in PFILE. This is called after reading a
PCH file, as the old line_table will be incorrect. */
void
-cpp_set_line_map (cpp_reader *pfile, struct line_maps *line_table)
+cpp_set_line_map (cpp_reader *pfile, class line_maps *line_table)
{
pfile->line_table = line_table;
}
cpp_destroy (cpp_reader *pfile)
{
cpp_context *context, *contextn;
+ struct def_pragma_macro *pmacro;
tokenrun *run, *runn;
int i;
while (CPP_BUFFER (pfile) != NULL)
_cpp_pop_buffer (pfile);
- if (pfile->out.base)
- free (pfile->out.base);
+ free (pfile->out.base);
if (pfile->macro_buffer)
{
free (pfile->comments.entries);
}
+ if (pfile->pushed_macros)
+ {
+ do
+ {
+ pmacro = pfile->pushed_macros;
+ pfile->pushed_macros = pmacro->next;
+ free (pmacro->name);
+ free (pmacro);
+ }
+ while (pfile->pushed_macros);
+ }
free (pfile);
}
"builtin" macros: these are handled by builtin_macro() in
macro.c. Builtin is somewhat of a misnomer -- the property of
interest is that these macros require special code to compute their
- expansions. The value is a "builtin_type" enumerator.
+ expansions. The value is a "cpp_builtin_type" enumerator.
operator_array holds the C++ named operators. These are keywords
which act as aliases for punctuators. In C++, they cannot be
B("__LINE__", BT_SPECLINE, true),
B("__INCLUDE_LEVEL__", BT_INCLUDE_LEVEL, true),
B("__COUNTER__", BT_COUNTER, true),
+ B("__has_attribute", BT_HAS_ATTRIBUTE, true),
+ B("__has_cpp_attribute", BT_HAS_ATTRIBUTE, true),
+ B("__has_builtin", BT_HAS_BUILTIN, true),
/* Keep builtins not used for -traditional-cpp at the end, and
update init_builtins() if any more are added. */
B("_Pragma", BT_PRAGMA, true),
/* Mark the C++ named operators in the hash table. */
static void
-mark_named_operators (cpp_reader *pfile)
+mark_named_operators (cpp_reader *pfile, int flags)
{
const struct builtin_operator *b;
b++)
{
cpp_hashnode *hp = cpp_lookup (pfile, b->name, b->len);
- hp->flags |= NODE_OPERATOR;
+ hp->flags |= flags;
hp->is_directive = 0;
hp->directive_index = b->value;
}
}
+/* Helper function of cpp_type2name. Return the string associated with
+ named operator TYPE. */
+const char *
+cpp_named_operator2name (enum cpp_ttype type)
+{
+ const struct builtin_operator *b;
+
+ for (b = operator_array;
+ b < (operator_array + ARRAY_SIZE (operator_array));
+ b++)
+ {
+ if (type == b->value)
+ return (const char *) b->name;
+ }
+
+ return NULL;
+}
+
void
cpp_init_special_builtins (cpp_reader *pfile)
{
for (b = builtin_array; b < builtin_array + n; b++)
{
+ if ((b->value == BT_HAS_ATTRIBUTE
+ || b->value == BT_HAS_BUILTIN)
+ && (CPP_OPTION (pfile, lang) == CLK_ASM
+ || pfile->cb.has_attribute == NULL))
+ continue;
cpp_hashnode *hp = cpp_lookup (pfile, b->name, b->len);
- hp->type = NT_MACRO;
- hp->flags |= NODE_BUILTIN;
- if (b->always_warn_if_redefined
- || CPP_OPTION (pfile, warn_builtin_macro_redefined))
+ hp->type = NT_BUILTIN_MACRO;
+ if (b->always_warn_if_redefined)
hp->flags |= NODE_WARN;
- hp->value.builtin = (enum builtin_type) b->value;
+ hp->value.builtin = (enum cpp_builtin_type) b->value;
}
}
+/* Restore macro C to builtin macro definition. */
+
+void
+_cpp_restore_special_builtin (cpp_reader *pfile, struct def_pragma_macro *c)
+{
+ size_t len = strlen (c->name);
+
+ for (const struct builtin_macro *b = builtin_array;
+ b < builtin_array + ARRAY_SIZE (builtin_array); b++)
+ if (b->len == len && memcmp (c->name, b->name, len + 1) == 0)
+ {
+ cpp_hashnode *hp = cpp_lookup (pfile, b->name, b->len);
+ hp->type = NT_BUILTIN_MACRO;
+ if (b->always_warn_if_redefined)
+ hp->flags |= NODE_WARN;
+ hp->value.builtin = (enum cpp_builtin_type) b->value;
+ }
+}
+
/* Read the builtins table above and enter them, and language-specific
macros, into the hash table. HOSTED is true if this is a hosted
environment. */
_cpp_define_builtin (pfile, "__STDC__ 1");
if (CPP_OPTION (pfile, cplusplus))
- _cpp_define_builtin (pfile, "__cplusplus 1");
+ {
+ if (CPP_OPTION (pfile, lang) == CLK_CXX2A
+ || CPP_OPTION (pfile, lang) == CLK_GNUCXX2A)
+ _cpp_define_builtin (pfile, "__cplusplus 201709L");
+ else if (CPP_OPTION (pfile, lang) == CLK_CXX17
+ || CPP_OPTION (pfile, lang) == CLK_GNUCXX17)
+ _cpp_define_builtin (pfile, "__cplusplus 201703L");
+ else if (CPP_OPTION (pfile, lang) == CLK_CXX14
+ || CPP_OPTION (pfile, lang) == CLK_GNUCXX14)
+ _cpp_define_builtin (pfile, "__cplusplus 201402L");
+ else if (CPP_OPTION (pfile, lang) == CLK_CXX11
+ || CPP_OPTION (pfile, lang) == CLK_GNUCXX11)
+ _cpp_define_builtin (pfile, "__cplusplus 201103L");
+ else
+ _cpp_define_builtin (pfile, "__cplusplus 199711L");
+ }
else if (CPP_OPTION (pfile, lang) == CLK_ASM)
_cpp_define_builtin (pfile, "__ASSEMBLER__ 1");
else if (CPP_OPTION (pfile, lang) == CLK_STDC94)
_cpp_define_builtin (pfile, "__STDC_VERSION__ 199409L");
+ else if (CPP_OPTION (pfile, lang) == CLK_STDC2X
+ || CPP_OPTION (pfile, lang) == CLK_GNUC2X)
+ _cpp_define_builtin (pfile, "__STDC_VERSION__ 202000L");
+ else if (CPP_OPTION (pfile, lang) == CLK_STDC17
+ || CPP_OPTION (pfile, lang) == CLK_GNUC17)
+ _cpp_define_builtin (pfile, "__STDC_VERSION__ 201710L");
+ else if (CPP_OPTION (pfile, lang) == CLK_STDC11
+ || CPP_OPTION (pfile, lang) == CLK_GNUC11)
+ _cpp_define_builtin (pfile, "__STDC_VERSION__ 201112L");
else if (CPP_OPTION (pfile, c99))
_cpp_define_builtin (pfile, "__STDC_VERSION__ 199901L");
+ if (CPP_OPTION (pfile, uliterals)
+ && !(CPP_OPTION (pfile, cplusplus)
+ && (CPP_OPTION (pfile, lang) == CLK_GNUCXX
+ || CPP_OPTION (pfile, lang) == CLK_CXX98)))
+ {
+ _cpp_define_builtin (pfile, "__STDC_UTF_16__ 1");
+ _cpp_define_builtin (pfile, "__STDC_UTF_32__ 1");
+ }
+
if (hosted)
_cpp_define_builtin (pfile, "__STDC_HOSTED__ 1");
else
}
/* Sanity-checks are dependent on command-line options, so it is
- called as a subroutine of cpp_read_main_file (). */
-#if ENABLE_CHECKING
+ called as a subroutine of cpp_read_main_file. */
+#if CHECKING_P
static void sanity_checks (cpp_reader *);
static void sanity_checks (cpp_reader *pfile)
{
void
cpp_post_options (cpp_reader *pfile)
{
+ int flags;
+
sanity_checks (pfile);
post_options (pfile);
/* Mark named operators before handling command line macros. */
+ flags = 0;
if (CPP_OPTION (pfile, cplusplus) && CPP_OPTION (pfile, operator_names))
- mark_named_operators (pfile);
+ flags |= NODE_OPERATOR;
+ if (CPP_OPTION (pfile, warn_cxx_operator_names))
+ flags |= NODE_DIAGNOSTIC | NODE_WARN_OPERATOR;
+ if (flags != 0)
+ mark_named_operators (pfile, flags);
}
/* Setup for processing input from the file named FNAME, or stdin if
const char *
cpp_read_main_file (cpp_reader *pfile, const char *fname)
{
+ const location_t loc = 0;
+
if (CPP_OPTION (pfile, deps.style) != DEPS_NONE)
{
if (!pfile->deps)
}
pfile->main_file
- = _cpp_find_file (pfile, fname, &pfile->no_search_path, false, 0);
+ = _cpp_find_file (pfile, fname, &pfile->no_search_path, false, 0, false,
+ loc);
if (_cpp_find_failed (pfile->main_file))
return NULL;
- _cpp_stack_file (pfile, pfile->main_file, false);
+ _cpp_stack_file (pfile, pfile->main_file, 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 = pfile->line_table->maps[pfile->line_table->used-1].to_file;
+ fname =
+ ORDINARY_MAP_FILE_NAME
+ ((LINEMAPS_LAST_ORDINARY_MAP (pfile->line_table)));
}
return fname;
}
pfile->state.in_directive = 0;
/* If it's a #line directive, handle it. */
- if (token1->type == CPP_NUMBER)
+ if (token1->type == CPP_NUMBER
+ && _cpp_handle_directive (pfile, token->flags & PREV_WHITE))
{
- _cpp_handle_directive (pfile, token->flags & PREV_WHITE);
read_original_directory (pfile);
return;
}
if (token->type != CPP_STRING
|| ! (token->val.str.len >= 5
- && token->val.str.text[token->val.str.len-2] == '/'
- && token->val.str.text[token->val.str.len-3] == '/'))
+ && IS_DIR_SEPARATOR (token->val.str.text[token->val.str.len-2])
+ && IS_DIR_SEPARATOR (token->val.str.text[token->val.str.len-3])))
{
_cpp_backup_tokens (pfile, 3);
return;
while (pfile->buffer)
_cpp_pop_buffer (pfile);
- if (CPP_OPTION (pfile, deps.style) != DEPS_NONE
- && deps_stream)
- {
- deps_write (pfile->deps, deps_stream, 72);
-
- if (CPP_OPTION (pfile, deps.phony_targets))
- deps_phony_targets (pfile->deps, deps_stream);
- }
+ if (CPP_OPTION (pfile, deps.style) != DEPS_NONE && deps_stream)
+ deps_write (pfile->deps, deps_stream,
+ CPP_OPTION (pfile, deps.phony_targets), 72);
/* Report on headers that could use multiple include guards. */
if (CPP_OPTION (pfile, print_include_names))
{
/* -Wtraditional is not useful in C++ mode. */
if (CPP_OPTION (pfile, cplusplus))
- CPP_OPTION (pfile, warn_traditional) = 0;
+ CPP_OPTION (pfile, cpp_warn_traditional) = 0;
/* Permanently disable macro expansion if we are rescanning
preprocessed text. Read preprocesed source in ISO mode. */
if (CPP_OPTION (pfile, traditional))
{
- CPP_OPTION (pfile, cplusplus_comments) = 0;
-
- /* Traditional CPP does not accurately track column information. */
- CPP_OPTION (pfile, show_column) = 0;
CPP_OPTION (pfile, trigraphs) = 0;
CPP_OPTION (pfile, warn_trigraphs) = 0;
}