summaryrefslogtreecommitdiffstats
path: root/libcpp
diff options
context:
space:
mode:
authorktietz <ktietz@138bc75d-0d04-0410-961f-82ee72b054a4>2009-11-11 18:37:19 +0000
committerktietz <ktietz@138bc75d-0d04-0410-961f-82ee72b054a4>2009-11-11 18:37:19 +0000
commit038c21f1c13e32ff37f03d9e0704e4e83fdee166 (patch)
treee54ead3691775dbb1e9d31588966d79cac024672 /libcpp
parent2dc819f38079d8edd542d89aa14d9831f2086e5e (diff)
downloadppe42-gcc-038c21f1c13e32ff37f03d9e0704e4e83fdee166.tar.gz
ppe42-gcc-038c21f1c13e32ff37f03d9e0704e4e83fdee166.zip
ChangeLog for libcpp
2009-11-11 Kai Tietz <kai.tietz@onevision.com> * directives.c (do_pragma_push_macro): New pragma handler. (do_pragma_pop_macro): Likewise. (_cpp_init_internal_pragmas): Add push_macro and pop_macro handler to internal pragmas. (lex_macro_node_from_str): Removed. (cpp_push_definition): Replace lex_macro_node_from_str by _cpp_lex_identifier. (cpp_pop_definition): Likewise. * internal.h (_cpp_lex_identifier): New prototype. (def_pragma_macro): New structure. (cpp_reader): New member pushed_macros. * lex.c (_cpp_lex_identifier): New function. (lex_identifier_intern): New function. * init.c (cpp_create_reader): Initialize pushed_macros member. (cpp_destroy): Free elements in pushed_macros member. * pch.c (_cpp_save_pushed_macros): New function. (_cpp_restore_pushed_macros): Likewise. (_cpp_restore_pushed_macros): Use _cpp_save_pushed_macros. (cpp_read_state): Use _cpp_restore_pushed_macros. ChangeLog for gcc 2009-11-11 Kai Tietz <kai.tietz@onevision.com> * config/i386/cygming.h (HANDLE_PRAGMA_PUSH_POP_MACRO): Removed. * c-pragma.c (def_pragma_macro_value): Likewise. (def_pragma_macro): Likewise. (pushed_macro_table): Likewise. (HANDLE_PRAGMA_PUSH_POP_MACRO): Remove guarded code. * doc/tm.texi (HANDLE_PRAGMA_PUSH_POP_MACRO): Removed. ChangeLog for gcc/testsuite 2009-11-11 Kai Tietz <kai.tietz@onevision.com> * g++.dg/torture/pushpop_macro.C: New testcase. * gcc.c-torture/execute/pushpop_macro.c: New testcase. * gcc.dg/cpp/pragma-pop_macro-1.c: Allow test for all targets. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@154098 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libcpp')
-rw-r--r--libcpp/ChangeLog23
-rw-r--r--libcpp/directives.c115
-rw-r--r--libcpp/init.c15
-rw-r--r--libcpp/internal.h14
-rw-r--r--libcpp/lex.c57
-rw-r--r--libcpp/pch.c136
6 files changed, 341 insertions, 19 deletions
diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog
index 5946b29dc56..c842e80c91d 100644
--- a/libcpp/ChangeLog
+++ b/libcpp/ChangeLog
@@ -1,3 +1,26 @@
+2009-11-11 Kai Tietz <kai.tietz@onevision.com>
+
+ * directives.c (do_pragma_push_macro): New pragma handler.
+ (do_pragma_pop_macro): Likewise.
+ (_cpp_init_internal_pragmas): Add push_macro and
+ pop_macro handler to internal pragmas.
+ (lex_macro_node_from_str): Removed.
+ (cpp_push_definition): Replace lex_macro_node_from_str
+ by _cpp_lex_identifier.
+ (cpp_pop_definition): Likewise.
+ * internal.h (_cpp_lex_identifier): New prototype.
+ (def_pragma_macro): New structure.
+ (cpp_reader): New member pushed_macros.
+ * lex.c (_cpp_lex_identifier): New function.
+ (lex_identifier_intern): New function.
+ * init.c (cpp_create_reader): Initialize pushed_macros
+ member.
+ (cpp_destroy): Free elements in pushed_macros member.
+ * pch.c (_cpp_save_pushed_macros): New function.
+ (_cpp_restore_pushed_macros): Likewise.
+ (_cpp_restore_pushed_macros): Use _cpp_save_pushed_macros.
+ (cpp_read_state): Use _cpp_restore_pushed_macros.
+
2009-10-19 Jakub Jelinek <jakub@redhat.com>
* charset.c (cpp_init_iconv): Initialize utf8_cset_desc.
diff --git a/libcpp/directives.c b/libcpp/directives.c
index 01bb599e266..aed940e56e1 100644
--- a/libcpp/directives.c
+++ b/libcpp/directives.c
@@ -126,6 +126,8 @@ static int parse_answer (cpp_reader *, struct answer **, int, source_location);
static cpp_hashnode *parse_assertion (cpp_reader *, struct answer **, int);
static struct answer ** find_answer (cpp_hashnode *, const struct answer *);
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 *);
/* This is the table of directive handlers. It is ordered by
frequency of occurrence; the numbers at the end are directive
@@ -1244,6 +1246,8 @@ _cpp_init_internal_pragmas (cpp_reader *pfile)
{
/* Pragmas in the global namespace. */
register_pragma_internal (pfile, 0, "once", do_pragma_once);
+ register_pragma_internal (pfile, 0, "push_macro", do_pragma_push_macro);
+ register_pragma_internal (pfile, 0, "pop_macro", do_pragma_pop_macro);
/* New GCC-specific pragmas should be put in the GCC namespace. */
register_pragma_internal (pfile, "GCC", "poison", do_pragma_poison);
@@ -1423,6 +1427,96 @@ 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)
+{
+ char *macroname, *dest;
+ const char *limit, *src;
+ const cpp_token *txt;
+ struct def_pragma_macro *c;
+
+ txt = get__Pragma_string (pfile);
+ if (!txt)
+ {
+ source_location 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;
+ }
+ 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);
+ c = XNEW (struct def_pragma_macro);
+ c->name = XNEWVAR (char, strlen (macroname) + 1);
+ strcpy (c->name, macroname);
+ c->next = pfile->pushed_macros;
+ c->value = cpp_push_definition (pfile, c->name);
+ pfile->pushed_macros = c;
+}
+
+/* Handle #pragma pop_macro(STRING). */
+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)
+ {
+ source_location 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)
+ {
+ if (!strcmp (c->name, macroname))
+ {
+ if (!l)
+ pfile->pushed_macros = c->next;
+ else
+ l->next = c->next;
+ cpp_pop_definition (pfile, c->name, c->value);
+ free (c->name);
+ free (c);
+ break;
+ }
+ l = c;
+ c = c->next;
+ }
+}
+
/* Handle #pragma GCC poison, to poison one or more identifiers so
that the lexer produces a hard error for each subsequent usage. */
static void
@@ -2225,28 +2319,11 @@ cpp_undef (cpp_reader *pfile, const char *macro)
run_directive (pfile, T_UNDEF, buf, len);
}
-/* Like lex_macro_node, but read the input from STR. */
-static cpp_hashnode *
-lex_macro_node_from_str (cpp_reader *pfile, const char *str)
-{
- size_t len = strlen (str);
- uchar *buf = (uchar *) alloca (len + 1);
- cpp_hashnode *node;
-
- memcpy (buf, str, len);
- buf[len] = '\n';
- cpp_push_buffer (pfile, buf, len, true);
- node = lex_macro_node (pfile, true);
- _cpp_pop_buffer (pfile);
-
- return node;
-}
-
/* If STR is a defined macro, return its definition node, else return NULL. */
cpp_macro *
cpp_push_definition (cpp_reader *pfile, const char *str)
{
- cpp_hashnode *node = lex_macro_node_from_str (pfile, str);
+ cpp_hashnode *node = _cpp_lex_identifier (pfile, str);
if (node && node->type == NT_MACRO)
return node->value.macro;
else
@@ -2258,7 +2335,7 @@ cpp_push_definition (cpp_reader *pfile, const char *str)
void
cpp_pop_definition (cpp_reader *pfile, const char *str, cpp_macro *dfn)
{
- cpp_hashnode *node = lex_macro_node_from_str (pfile, str);
+ cpp_hashnode *node = _cpp_lex_identifier (pfile, str);
if (node == NULL)
return;
diff --git a/libcpp/init.c b/libcpp/init.c
index e5be4e2b1b4..522ddbbb638 100644
--- a/libcpp/init.c
+++ b/libcpp/init.c
@@ -216,6 +216,9 @@ cpp_create_reader (enum c_lang lang, hash_table *table,
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;
+
/* The expression parser stack. */
_cpp_expand_op_stack (pfile);
@@ -245,6 +248,7 @@ void
cpp_destroy (cpp_reader *pfile)
{
cpp_context *context, *contextn;
+ struct def_pragma_macro *pmacro;
tokenrun *run, *runn;
int i;
@@ -296,6 +300,17 @@ cpp_destroy (cpp_reader *pfile)
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);
}
diff --git a/libcpp/internal.h b/libcpp/internal.h
index aaa231c2ab1..555874c1d47 100644
--- a/libcpp/internal.h
+++ b/libcpp/internal.h
@@ -305,6 +305,16 @@ struct cpp_buffer
struct cset_converter input_cset_desc;
};
+/* The list of saved macros by push_macro pragma. */
+struct def_pragma_macro {
+ /* Chain element to previous saved macro. */
+ struct def_pragma_macro *next;
+ /* Name of the macro. */
+ char *name;
+ /* The stored macro content. */
+ cpp_macro *value;
+};
+
/* A cpp_reader encapsulates the "state" of a pre-processor run.
Applying cpp_get_token repeatedly yields a stream of pre-processor
tokens. Usually, there is only one cpp_reader object active. */
@@ -475,6 +485,9 @@ struct cpp_reader
/* Table of comments, when state.save_comments is true. */
cpp_comment_table comments;
+
+ /* List of saved macros by push_macro. */
+ struct def_pragma_macro *pushed_macros;
};
/* Character classes. Based on the more primitive macros in safe-ctype.h.
@@ -575,6 +588,7 @@ extern const cpp_token *_cpp_lex_token (cpp_reader *);
extern cpp_token *_cpp_lex_direct (cpp_reader *);
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 *);
/* In init.c. */
extern void _cpp_maybe_push_include_file (cpp_reader *);
diff --git a/libcpp/lex.c b/libcpp/lex.c
index 55bffa9a326..ac28f92e640 100644
--- a/libcpp/lex.c
+++ b/libcpp/lex.c
@@ -504,6 +504,63 @@ forms_identifier_p (cpp_reader *pfile, int first,
return false;
}
+/* 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));
+
+ /* Rarely, identifiers require diagnostics when lexed. */
+ if (__builtin_expect ((result->flags & NODE_DIAGNOSTIC)
+ && !pfile->state.skipping, 0))
+ {
+ /* It is allowed to poison the same identifier twice. */
+ if ((result->flags & NODE_POISONED) && !pfile->state.poisoned_ok)
+ cpp_error (pfile, CPP_DL_ERROR, "attempt to use poisoned \"%s\"",
+ NODE_NAME (result));
+
+ /* Constraint 6.10.3.5: __VA_ARGS__ should only appear in the
+ replacement list of a variadic macro. */
+ if (result == pfile->spec_nodes.n__VA_ARGS__
+ && !pfile->state.va_args_ok)
+ cpp_error (pfile, CPP_DL_PEDWARN,
+ "__VA_ARGS__ can only appear in the expansion"
+ " of a C99 variadic macro");
+
+ /* For -Wc++-compat, warn about use of C++ named operators. */
+ if (result->flags & NODE_WARN_OPERATOR)
+ cpp_error (pfile, CPP_DL_WARNING,
+ "identifier \"%s\" is a special operator name in C++",
+ NODE_NAME (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 BUFFER->CUR - 1. */
static cpp_hashnode *
lex_identifier (cpp_reader *pfile, const uchar *base, bool starts_ucn,
diff --git a/libcpp/pch.c b/libcpp/pch.c
index f656418a192..c70759a996d 100644
--- a/libcpp/pch.c
+++ b/libcpp/pch.c
@@ -33,6 +33,8 @@ static int comp_hashnodes (const void *, const void *);
static int collect_ht_nodes (cpp_reader *, cpp_hashnode *, void *);
static int write_defs (cpp_reader *, cpp_hashnode *, void *);
static int save_macros (cpp_reader *, cpp_hashnode *, void *);
+static int _cpp_save_pushed_macros (cpp_reader *, FILE *);
+static int _cpp_restore_pushed_macros (cpp_reader *, FILE *);
/* This structure represents a macro definition on disk. */
struct macrodef_struct
@@ -378,9 +380,140 @@ cpp_write_pch_state (cpp_reader *r, FILE *f)
return -1;
}
+ /* Write saved macros. */
+ if (! _cpp_save_pushed_macros (r, f))
+ {
+ cpp_errno (r, CPP_DL_ERROR, "while writing precompiled header");
+ return -1;
+ }
+
return 0;
}
+static int
+_cpp_restore_pushed_macros (cpp_reader *r, FILE *f)
+{
+ size_t count_saved = 0;
+ size_t i;
+ struct def_pragma_macro *p;
+ size_t nlen;
+ cpp_hashnode *h = NULL;
+ cpp_macro *m;
+ uchar *defn;
+ size_t defnlen;
+
+ if (fread (&count_saved, sizeof (count_saved), 1, f) != 1)
+ return 0;
+ if (! count_saved)
+ return 1;
+ for (i = 0; i < count_saved; i++)
+ {
+ if (fread (&nlen, sizeof (nlen), 1, f) != 1)
+ return 0;
+ p = XNEW (struct def_pragma_macro);
+ p->name = XNEWVAR (char, nlen + 1);
+ p->name[nlen] = 0;
+ if (fread (p->name, nlen, 1, f) != 1)
+ return 0;
+ /* Save old state. */
+ m = cpp_push_definition (r, p->name);
+ if (fread (&defnlen, sizeof (defnlen), 1, f) != 1)
+ return 0;
+ defn = XNEWVAR (uchar, defnlen + 2);
+ defn[defnlen] = '\n';
+ defn[defnlen + 1] = 0;
+
+ if (fread (defn, defnlen, 1, f) != 1)
+ return 0;
+ cpp_pop_definition (r, p->name, NULL);
+ {
+ size_t namelen;
+ uchar *dn;
+
+ namelen = ustrcspn (defn, "( \n");
+ h = cpp_lookup (r, defn, namelen);
+ dn = defn + namelen;
+
+ h->type = NT_VOID;
+ h->flags &= ~(NODE_POISONED|NODE_BUILTIN|NODE_DISABLED|NODE_USED);
+ if (cpp_push_buffer (r, dn, ustrchr (dn, '\n') - dn, true)
+ != NULL)
+ {
+ _cpp_clean_line (r);
+ if (!_cpp_create_definition (r, h))
+ abort ();
+ _cpp_pop_buffer (r);
+ }
+ else
+ abort ();
+ }
+ p->value = cpp_push_definition (r, p->name);
+
+ free (defn);
+ p->next = r->pushed_macros;
+ r->pushed_macros = p;
+ /* Restore current state. */
+ cpp_pop_definition (r, p->name, m);
+ }
+ return 1;
+}
+
+static int
+_cpp_save_pushed_macros (cpp_reader *r, FILE *f)
+{
+ size_t count_saved = 0;
+ size_t i;
+ struct def_pragma_macro *p,**pp;
+ cpp_hashnode *node;
+ cpp_macro *m;
+ size_t defnlen;
+ const uchar *defn;
+
+ /* Get count. */
+ p = r->pushed_macros;
+ while (p != NULL)
+ {
+ count_saved++;
+ p = p->next;
+ }
+ if (fwrite (&count_saved, sizeof (count_saved), 1, f) != 1)
+ return 0;
+ if (!count_saved)
+ return 1;
+
+ pp = (struct def_pragma_macro **) alloca (sizeof (struct def_pragma_macro *)
+ * count_saved);
+ /* Store them in reverse order. */
+ p = r->pushed_macros;
+ i = count_saved;
+ while (p != NULL)
+ {
+ --i;
+ pp[i] = p;
+ p = p->next;
+ }
+ for (i = 0; i < count_saved; i++)
+ {
+ /* Save old state. */
+ m = cpp_push_definition (r, pp[i]->name);
+ /* Set temporary macro name to saved state. */
+ cpp_pop_definition (r, pp[i]->name, pp[i]->value);
+ node = _cpp_lex_identifier (r, pp[i]->name);
+ defnlen = strlen (pp[i]->name);
+ if (fwrite (&defnlen, sizeof (size_t), 1, f) != 1
+ || fwrite (pp[i]->name, defnlen, 1, f) != 1)
+ return 0;
+ defn = cpp_macro_definition (r, node);
+ defnlen = ustrlen (defn);
+ if (fwrite (&defnlen, sizeof (size_t), 1, f) != 1
+ || fwrite (defn, defnlen, 1, f) != 1)
+ return 0;
+ /* Restore current state. */
+ cpp_pop_definition (r, pp[i]->name, m);
+ }
+ return 1;
+}
+
/* Data structure to transform hash table nodes into a sorted list */
@@ -752,6 +885,9 @@ cpp_read_state (cpp_reader *r, const char *name, FILE *f,
if (!r->counter)
r->counter = counter;
+ /* Read pushed macros. */
+ if (! _cpp_restore_pushed_macros (r, f))
+ goto error;
return 0;
error:
OpenPOWER on IntegriCloud