aboutsummaryrefslogtreecommitdiff
path: root/libcpp
diff options
context:
space:
mode:
Diffstat (limited to 'libcpp')
-rw-r--r--libcpp/charset.cc34
-rw-r--r--libcpp/directives.cc175
-rw-r--r--libcpp/errors.cc16
-rw-r--r--libcpp/include/cpplib.h13
-rw-r--r--libcpp/internal.h1
-rw-r--r--libcpp/lex.cc33
6 files changed, 121 insertions, 151 deletions
diff --git a/libcpp/charset.cc b/libcpp/charset.cc
index c7d4508..bcfc10c 100644
--- a/libcpp/charset.cc
+++ b/libcpp/charset.cc
@@ -2600,19 +2600,6 @@ cpp_interpret_string (cpp_reader *pfile, const cpp_string *from, size_t count,
return cpp_interpret_string_1 (pfile, from, count, to, type, NULL, NULL);
}
-/* A "do nothing" diagnostic-handling callback for use by
- cpp_interpret_string_ranges, so that it can temporarily suppress
- diagnostic-handling. */
-
-static bool
-noop_diagnostic_cb (cpp_reader *, enum cpp_diagnostic_level,
- enum cpp_warning_reason, rich_location *,
- const char *, va_list *)
-{
- /* no-op. */
- return true;
-}
-
/* This function mimics the behavior of cpp_interpret_string, but
rather than generating a string in the execution character set,
*OUT is written to with the source code ranges of the characters
@@ -2652,20 +2639,9 @@ cpp_interpret_string_ranges (cpp_reader *pfile, const cpp_string *from,
failing, rather than being emitted as a user-visible diagnostic.
If an diagnostic does occur, we should see it via the return value of
cpp_interpret_string_1. */
- bool (*saved_diagnostic_handler) (cpp_reader *, enum cpp_diagnostic_level,
- enum cpp_warning_reason, rich_location *,
- const char *, va_list *)
- ATTRIBUTE_CPP_PPDIAG (5, 0);
-
- saved_diagnostic_handler = pfile->cb.diagnostic;
- pfile->cb.diagnostic = noop_diagnostic_cb;
-
+ cpp_auto_suppress_diagnostics suppress {pfile};
bool result = cpp_interpret_string_1 (pfile, from, count, NULL, type,
loc_readers, out);
-
- /* Restore the saved diagnostic-handler. */
- pfile->cb.diagnostic = saved_diagnostic_handler;
-
if (!result)
return "cpp_interpret_string_1 failed";
@@ -2701,17 +2677,11 @@ static unsigned
count_source_chars (cpp_reader *pfile, cpp_string str, cpp_ttype type)
{
cpp_string str2 = { 0, 0 };
- bool (*saved_diagnostic_handler) (cpp_reader *, enum cpp_diagnostic_level,
- enum cpp_warning_reason, rich_location *,
- const char *, va_list *)
- ATTRIBUTE_CPP_PPDIAG (5, 0);
- saved_diagnostic_handler = pfile->cb.diagnostic;
- pfile->cb.diagnostic = noop_diagnostic_cb;
+ cpp_auto_suppress_diagnostics suppress {pfile};
convert_f save_func = pfile->narrow_cset_desc.func;
pfile->narrow_cset_desc.func = convert_count_chars;
bool ret = cpp_interpret_string (pfile, &str, 1, &str2, type);
pfile->narrow_cset_desc.func = save_func;
- pfile->cb.diagnostic = saved_diagnostic_handler;
if (ret)
{
if (str2.text != str.text)
diff --git a/libcpp/directives.cc b/libcpp/directives.cc
index 50fa8ace2..bc4a95b 100644
--- a/libcpp/directives.cc
+++ b/libcpp/directives.cc
@@ -141,7 +141,8 @@ static cpp_macro **find_answer (cpp_hashnode *, const cpp_macro *);
static void handle_assertion (cpp_reader *, const char *, int);
static void do_pragma_push_macro (cpp_reader *);
static void do_pragma_pop_macro (cpp_reader *);
-static void cpp_pop_definition (cpp_reader *, struct def_pragma_macro *);
+static void cpp_pop_definition (cpp_reader *, def_pragma_macro *,
+ cpp_hashnode *);
/* This is the table of directive handlers. All extensions other than
#warning, #include_next, and #import are deprecated. The name is
@@ -2085,55 +2086,95 @@ do_pragma_once (cpp_reader *pfile)
_cpp_mark_file_once_only (pfile, pfile->buffer->file);
}
-/* Handle #pragma push_macro(STRING). */
-static void
-do_pragma_push_macro (cpp_reader *pfile)
+/* Helper for #pragma {push,pop}_macro. Destringize STR and
+ lex it into an identifier, returning the hash node for it. */
+
+static cpp_hashnode *
+lex_identifier_from_string (cpp_reader *pfile, cpp_string str)
{
+ auto src = (const uchar *) memchr (str.text, '"', str.len);
+ gcc_checking_assert (src);
+ ++src;
+ const auto limit = str.text + str.len - 1;
+ gcc_checking_assert (*limit == '"' && limit >= src);
+ const auto ident = XALLOCAVEC (uchar, limit - src + 1);
+ auto dest = ident;
+ while (src != limit)
+ {
+ /* We know there is a character following the backslash. */
+ if (*src == '\\' && (src[1] == '\\' || src[1] == '"'))
+ src++;
+ *dest++ = *src++;
+ }
+
+ /* We reserved a spot for the newline with the + 1 when allocating IDENT.
+ Push a buffer containing the identifier to lex. */
+ *dest = '\n';
+ cpp_push_buffer (pfile, ident, dest - ident, true);
+ _cpp_clean_line (pfile);
+ pfile->cur_token = _cpp_temp_token (pfile);
+ cpp_token *tok;
+ {
+ /* Suppress diagnostics during lexing so that we silently ignore invalid
+ input, as seems to be the common practice for this pragma. */
+ cpp_auto_suppress_diagnostics suppress {pfile};
+ tok = _cpp_lex_direct (pfile);
+ }
+
cpp_hashnode *node;
- size_t defnlen;
- const uchar *defn = NULL;
- char *macroname, *dest;
- const char *limit, *src;
- const cpp_token *txt;
- struct def_pragma_macro *c;
+ if (tok->type != CPP_NAME || pfile->buffer->cur != pfile->buffer->rlimit)
+ node = nullptr;
+ else
+ node = tok->val.node.node;
- txt = get__Pragma_string (pfile);
- if (!txt)
+ _cpp_pop_buffer (pfile);
+ return node;
+}
+
+/* Common processing for #pragma {push,pop}_macro. */
+
+static cpp_hashnode *
+push_pop_macro_common (cpp_reader *pfile, const char *type)
+{
+ const cpp_token *const txt = get__Pragma_string (pfile);
+ ++pfile->keep_tokens;
+ cpp_hashnode *node;
+ if (txt)
{
- location_t src_loc = pfile->cur_token[-1].src_loc;
- cpp_error_with_line (pfile, CPP_DL_ERROR, src_loc, 0,
- "invalid %<#pragma push_macro%> directive");
check_eol (pfile, false);
skip_rest_of_line (pfile);
- return;
+ node = lex_identifier_from_string (pfile, txt->val.str);
}
- dest = macroname = (char *) alloca (txt->val.str.len + 2);
- src = (const char *) (txt->val.str.text + 1 + (txt->val.str.text[0] == 'L'));
- limit = (const char *) (txt->val.str.text + txt->val.str.len - 1);
- while (src < limit)
+ else
{
- /* We know there is a character following the backslash. */
- if (*src == '\\' && (src[1] == '\\' || src[1] == '"'))
- src++;
- *dest++ = *src++;
+ node = nullptr;
+ location_t src_loc = pfile->cur_token[-1].src_loc;
+ cpp_error_with_line (pfile, CPP_DL_ERROR, src_loc, 0,
+ "invalid %<#pragma %s_macro%> directive", type);
+ skip_rest_of_line (pfile);
}
- *dest = 0;
- check_eol (pfile, false);
- skip_rest_of_line (pfile);
- c = XNEW (struct def_pragma_macro);
- memset (c, 0, sizeof (struct def_pragma_macro));
- c->name = XNEWVAR (char, strlen (macroname) + 1);
- strcpy (c->name, macroname);
+ --pfile->keep_tokens;
+ return node;
+}
+
+/* Handle #pragma push_macro(STRING). */
+static void
+do_pragma_push_macro (cpp_reader *pfile)
+{
+ const auto node = push_pop_macro_common (pfile, "push");
+ if (!node)
+ return;
+ const auto c = XCNEW (def_pragma_macro);
+ c->name = xstrdup ((const char *) NODE_NAME (node));
c->next = pfile->pushed_macros;
- node = _cpp_lex_identifier (pfile, c->name);
if (node->type == NT_VOID)
c->is_undef = 1;
else if (node->type == NT_BUILTIN_MACRO)
c->is_builtin = 1;
else
{
- defn = cpp_macro_definition (pfile, node);
- defnlen = ustrlen (defn);
+ const auto defn = cpp_macro_definition (pfile, node);
+ const size_t defnlen = ustrlen (defn);
c->definition = XNEWVEC (uchar, defnlen + 2);
c->definition[defnlen] = '\n';
c->definition[defnlen + 1] = 0;
@@ -2150,50 +2191,24 @@ do_pragma_push_macro (cpp_reader *pfile)
static void
do_pragma_pop_macro (cpp_reader *pfile)
{
- char *macroname, *dest;
- const char *limit, *src;
- const cpp_token *txt;
- struct def_pragma_macro *l = NULL, *c = pfile->pushed_macros;
- txt = get__Pragma_string (pfile);
- if (!txt)
- {
- location_t src_loc = pfile->cur_token[-1].src_loc;
- cpp_error_with_line (pfile, CPP_DL_ERROR, src_loc, 0,
- "invalid %<#pragma pop_macro%> directive");
- check_eol (pfile, false);
- skip_rest_of_line (pfile);
- return;
- }
- dest = macroname = (char *) alloca (txt->val.str.len + 2);
- src = (const char *) (txt->val.str.text + 1 + (txt->val.str.text[0] == 'L'));
- limit = (const char *) (txt->val.str.text + txt->val.str.len - 1);
- while (src < limit)
- {
- /* We know there is a character following the backslash. */
- if (*src == '\\' && (src[1] == '\\' || src[1] == '"'))
- src++;
- *dest++ = *src++;
- }
- *dest = 0;
- check_eol (pfile, false);
- skip_rest_of_line (pfile);
-
- while (c != NULL)
+ const auto node = push_pop_macro_common (pfile, "pop");
+ if (!node)
+ return;
+ for (def_pragma_macro *c = pfile->pushed_macros, *l = nullptr; c; c = c->next)
{
- if (!strcmp (c->name, macroname))
+ if (!strcmp (c->name, (const char *) NODE_NAME (node)))
{
if (!l)
pfile->pushed_macros = c->next;
else
l->next = c->next;
- cpp_pop_definition (pfile, c);
+ cpp_pop_definition (pfile, c, node);
free (c->definition);
free (c->name);
free (c);
break;
}
l = c;
- c = c->next;
}
}
@@ -3109,12 +3124,8 @@ cpp_undef (cpp_reader *pfile, const char *macro)
/* Replace a previous definition DEF of the macro STR. If DEF is NULL,
or first element is zero, then the macro should be undefined. */
static void
-cpp_pop_definition (cpp_reader *pfile, struct def_pragma_macro *c)
+cpp_pop_definition (cpp_reader *pfile, def_pragma_macro *c, cpp_hashnode *node)
{
- cpp_hashnode *node = _cpp_lex_identifier (pfile, c->name);
- if (node == NULL)
- return;
-
if (pfile->cb.before_define)
pfile->cb.before_define (pfile);
@@ -3136,29 +3147,23 @@ cpp_pop_definition (cpp_reader *pfile, struct def_pragma_macro *c)
}
{
- size_t namelen;
- const uchar *dn;
- cpp_hashnode *h = NULL;
- cpp_buffer *nbuf;
-
- namelen = ustrcspn (c->definition, "( \n");
- h = cpp_lookup (pfile, c->definition, namelen);
- dn = c->definition + namelen;
-
- nbuf = cpp_push_buffer (pfile, dn, ustrchr (dn, '\n') - dn, true);
+ const auto namelen = ustrcspn (c->definition, "( \n");
+ const auto dn = c->definition + namelen;
+ const auto nbuf = cpp_push_buffer (pfile, dn, ustrchr (dn, '\n') - dn,
+ true);
if (nbuf != NULL)
{
_cpp_clean_line (pfile);
nbuf->sysp = 1;
- if (!_cpp_create_definition (pfile, h, 0))
+ if (!_cpp_create_definition (pfile, node, 0))
abort ();
_cpp_pop_buffer (pfile);
}
else
abort ();
- h->value.macro->line = c->line;
- h->value.macro->syshdr = c->syshdr;
- h->value.macro->used = c->used;
+ node->value.macro->line = c->line;
+ node->value.macro->syshdr = c->syshdr;
+ node->value.macro->used = c->used;
}
}
diff --git a/libcpp/errors.cc b/libcpp/errors.cc
index 5d8ceb9..ad45f61 100644
--- a/libcpp/errors.cc
+++ b/libcpp/errors.cc
@@ -350,3 +350,19 @@ cpp_errno_filename (cpp_reader *pfile, enum cpp_diagnostic_level level,
return cpp_error_at (pfile, level, loc, "%s: %s", filename,
xstrerror (errno));
}
+
+cpp_auto_suppress_diagnostics::cpp_auto_suppress_diagnostics (cpp_reader *pfile)
+ : m_pfile (pfile), m_cb (pfile->cb.diagnostic)
+{
+ m_pfile->cb.diagnostic
+ = [] (cpp_reader *, cpp_diagnostic_level, cpp_warning_reason,
+ rich_location *, const char *, va_list *)
+ {
+ return true;
+ };
+}
+
+cpp_auto_suppress_diagnostics::~cpp_auto_suppress_diagnostics ()
+{
+ m_pfile->cb.diagnostic = m_cb;
+}
diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h
index e64c2b6..be367b1 100644
--- a/libcpp/include/cpplib.h
+++ b/libcpp/include/cpplib.h
@@ -1662,4 +1662,17 @@ enum cpp_xid_property {
unsigned int cpp_check_xid_property (cppchar_t c);
+/* In errors.cc */
+
+/* RAII class to suppress CPP diagnostics in the current scope. */
+class cpp_auto_suppress_diagnostics
+{
+ public:
+ explicit cpp_auto_suppress_diagnostics (cpp_reader *pfile);
+ ~cpp_auto_suppress_diagnostics ();
+ private:
+ cpp_reader *const m_pfile;
+ const decltype (cpp_callbacks::diagnostic) m_cb;
+};
+
#endif /* ! LIBCPP_CPPLIB_H */
diff --git a/libcpp/internal.h b/libcpp/internal.h
index 2379fbb..6c2a36e 100644
--- a/libcpp/internal.h
+++ b/libcpp/internal.h
@@ -794,7 +794,6 @@ extern cpp_token *_cpp_lex_direct (cpp_reader *);
extern unsigned char *_cpp_spell_ident_ucns (unsigned char *, cpp_hashnode *);
extern int _cpp_equiv_tokens (const cpp_token *, const cpp_token *);
extern void _cpp_init_tokenrun (tokenrun *, unsigned int);
-extern cpp_hashnode *_cpp_lex_identifier (cpp_reader *, const char *);
extern int _cpp_remaining_tokens_num_in_context (cpp_context *);
extern void _cpp_init_lexer (void);
static inline void *_cpp_reserve_room (cpp_reader *pfile, size_t have,
diff --git a/libcpp/lex.cc b/libcpp/lex.cc
index 66ff6ce..40c5318 100644
--- a/libcpp/lex.cc
+++ b/libcpp/lex.cc
@@ -2091,39 +2091,6 @@ identifier_diagnostics_on_lex (cpp_reader *pfile, cpp_hashnode *node)
NODE_NAME (node));
}
-/* Helper function to get the cpp_hashnode of the identifier BASE. */
-static cpp_hashnode *
-lex_identifier_intern (cpp_reader *pfile, const uchar *base)
-{
- cpp_hashnode *result;
- const uchar *cur;
- unsigned int len;
- unsigned int hash = HT_HASHSTEP (0, *base);
-
- cur = base + 1;
- while (ISIDNUM (*cur))
- {
- hash = HT_HASHSTEP (hash, *cur);
- cur++;
- }
- len = cur - base;
- hash = HT_HASHFINISH (hash, len);
- result = CPP_HASHNODE (ht_lookup_with_hash (pfile->hash_table,
- base, len, hash, HT_ALLOC));
- identifier_diagnostics_on_lex (pfile, result);
- return result;
-}
-
-/* Get the cpp_hashnode of an identifier specified by NAME in
- the current cpp_reader object. If none is found, NULL is returned. */
-cpp_hashnode *
-_cpp_lex_identifier (cpp_reader *pfile, const char *name)
-{
- cpp_hashnode *result;
- result = lex_identifier_intern (pfile, (uchar *) name);
- return result;
-}
-
/* Lex an identifier starting at BASE. BUFFER->CUR is expected to point
one past the first character at BASE, which may be a (possibly multi-byte)
character if STARTS_UCN is true. */