mirror of git://gcc.gnu.org/git/gcc.git
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. From-SVN: r154098
This commit is contained in:
parent
110532c838
commit
17e7cb8550
|
@ -1,3 +1,15 @@
|
||||||
|
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.
|
||||||
|
|
||||||
2009-11-11 Basile Starynkevitch <basile@starynkevitch.net>
|
2009-11-11 Basile Starynkevitch <basile@starynkevitch.net>
|
||||||
* doc/plugins.texi (Registering custom attributes): section
|
* doc/plugins.texi (Registering custom attributes): section
|
||||||
renamed as (Registering custom attributes or pragmas).
|
renamed as (Registering custom attributes or pragmas).
|
||||||
|
|
142
gcc/c-pragma.c
142
gcc/c-pragma.c
|
@ -244,144 +244,6 @@ handle_pragma_pack (cpp_reader * ARG_UNUSED (dummy))
|
||||||
}
|
}
|
||||||
#endif /* HANDLE_PRAGMA_PACK */
|
#endif /* HANDLE_PRAGMA_PACK */
|
||||||
|
|
||||||
struct GTY(()) def_pragma_macro_value {
|
|
||||||
struct def_pragma_macro_value *prev;
|
|
||||||
cpp_macro *value;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct GTY(()) def_pragma_macro {
|
|
||||||
hashval_t hash;
|
|
||||||
const char *name;
|
|
||||||
struct def_pragma_macro_value value;
|
|
||||||
};
|
|
||||||
|
|
||||||
static GTY((param_is (struct def_pragma_macro))) htab_t pushed_macro_table;
|
|
||||||
|
|
||||||
#ifdef HANDLE_PRAGMA_PUSH_POP_MACRO
|
|
||||||
/* Hash table control functions for pushed_macro_table. */
|
|
||||||
static hashval_t
|
|
||||||
dpm_hash (const void *p)
|
|
||||||
{
|
|
||||||
return ((const struct def_pragma_macro *)p)->hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
dpm_eq (const void *pa, const void *pb)
|
|
||||||
{
|
|
||||||
const struct def_pragma_macro *const a = (const struct def_pragma_macro *) pa,
|
|
||||||
*const b = (const struct def_pragma_macro *) pb;
|
|
||||||
return a->hash == b->hash && strcmp (a->name, b->name) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* #pragma push_macro("MACRO_NAME")
|
|
||||||
#pragma pop_macro("MACRO_NAME") */
|
|
||||||
|
|
||||||
static void
|
|
||||||
handle_pragma_push_macro (cpp_reader *reader)
|
|
||||||
{
|
|
||||||
tree x, id = 0;
|
|
||||||
enum cpp_ttype token;
|
|
||||||
struct def_pragma_macro dummy, *c;
|
|
||||||
const char *macroname;
|
|
||||||
void **slot;
|
|
||||||
|
|
||||||
if (pragma_lex (&x) != CPP_OPEN_PAREN)
|
|
||||||
GCC_BAD ("missing %<(%> after %<#pragma push_macro%> - ignored");
|
|
||||||
|
|
||||||
token = pragma_lex (&id);
|
|
||||||
|
|
||||||
/* Silently ignore */
|
|
||||||
if (token == CPP_CLOSE_PAREN)
|
|
||||||
return;
|
|
||||||
if (token != CPP_STRING)
|
|
||||||
GCC_BAD ("invalid constant in %<#pragma push_macro%> - ignored");
|
|
||||||
|
|
||||||
if (pragma_lex (&x) != CPP_CLOSE_PAREN)
|
|
||||||
GCC_BAD ("missing %<)%> after %<#pragma push_macro%> - ignored");
|
|
||||||
|
|
||||||
if (pragma_lex (&x) != CPP_EOF)
|
|
||||||
warning (OPT_Wpragmas, "junk at end of %<#pragma push_macro%>");
|
|
||||||
|
|
||||||
/* Check for empty string, and silently ignore. */
|
|
||||||
if (TREE_STRING_LENGTH (id) < 1)
|
|
||||||
return;
|
|
||||||
macroname = TREE_STRING_POINTER (id);
|
|
||||||
|
|
||||||
if (pushed_macro_table == NULL)
|
|
||||||
pushed_macro_table = htab_create_ggc (15, dpm_hash, dpm_eq, 0);
|
|
||||||
|
|
||||||
dummy.hash = htab_hash_string (macroname);
|
|
||||||
dummy.name = macroname;
|
|
||||||
slot = htab_find_slot_with_hash (pushed_macro_table, &dummy,
|
|
||||||
dummy.hash, INSERT);
|
|
||||||
c = (struct def_pragma_macro *) *slot;
|
|
||||||
if (c == NULL)
|
|
||||||
{
|
|
||||||
*slot = c = GGC_NEW (struct def_pragma_macro);
|
|
||||||
c->hash = dummy.hash;
|
|
||||||
c->name = ggc_alloc_string (macroname, TREE_STRING_LENGTH (id) - 1);
|
|
||||||
c->value.prev = NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
struct def_pragma_macro_value *v;
|
|
||||||
v = GGC_NEW (struct def_pragma_macro_value);
|
|
||||||
*v = c->value;
|
|
||||||
c->value.prev = v;
|
|
||||||
}
|
|
||||||
|
|
||||||
c->value.value = cpp_push_definition (reader, macroname);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
handle_pragma_pop_macro (cpp_reader *reader)
|
|
||||||
{
|
|
||||||
tree x, id = 0;
|
|
||||||
enum cpp_ttype token;
|
|
||||||
struct def_pragma_macro dummy, *c;
|
|
||||||
const char *macroname;
|
|
||||||
void **slot = NULL;
|
|
||||||
|
|
||||||
if (pragma_lex (&x) != CPP_OPEN_PAREN)
|
|
||||||
GCC_BAD ("missing %<(%> after %<#pragma pop_macro%> - ignored");
|
|
||||||
|
|
||||||
token = pragma_lex (&id);
|
|
||||||
|
|
||||||
/* Silently ignore */
|
|
||||||
if (token == CPP_CLOSE_PAREN)
|
|
||||||
return;
|
|
||||||
if (token != CPP_STRING)
|
|
||||||
GCC_BAD ("invalid constant in %<#pragma pop_macro%> - ignored");
|
|
||||||
|
|
||||||
if (pragma_lex (&x) != CPP_CLOSE_PAREN)
|
|
||||||
GCC_BAD ("missing %<)%> after %<#pragma pop_macro%> - ignored");
|
|
||||||
|
|
||||||
if (pragma_lex (&x) != CPP_EOF)
|
|
||||||
warning (OPT_Wpragmas, "junk at end of %<#pragma pop_macro%>");
|
|
||||||
|
|
||||||
/* Check for empty string, and silently ignore. */
|
|
||||||
if (TREE_STRING_LENGTH (id) < 1)
|
|
||||||
return;
|
|
||||||
macroname = TREE_STRING_POINTER (id);
|
|
||||||
|
|
||||||
dummy.hash = htab_hash_string (macroname);
|
|
||||||
dummy.name = macroname;
|
|
||||||
if (pushed_macro_table)
|
|
||||||
slot = htab_find_slot_with_hash (pushed_macro_table, &dummy,
|
|
||||||
dummy.hash, NO_INSERT);
|
|
||||||
if (slot == NULL)
|
|
||||||
return;
|
|
||||||
c = (struct def_pragma_macro *) *slot;
|
|
||||||
|
|
||||||
cpp_pop_definition (reader, c->name, c->value.value);
|
|
||||||
|
|
||||||
if (c->value.prev)
|
|
||||||
c->value = *c->value.prev;
|
|
||||||
else
|
|
||||||
htab_clear_slot (pushed_macro_table, slot);
|
|
||||||
}
|
|
||||||
#endif /* HANDLE_PRAGMA_PUSH_POP_MACRO */
|
|
||||||
|
|
||||||
static GTY(()) tree pending_weaks;
|
static GTY(()) tree pending_weaks;
|
||||||
|
|
||||||
#ifdef HANDLE_PRAGMA_WEAK
|
#ifdef HANDLE_PRAGMA_WEAK
|
||||||
|
@ -1422,10 +1284,6 @@ init_pragma (void)
|
||||||
c_register_pragma (0, "pack", handle_pragma_pack);
|
c_register_pragma (0, "pack", handle_pragma_pack);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#ifdef HANDLE_PRAGMA_PUSH_POP_MACRO
|
|
||||||
c_register_pragma (0 ,"push_macro", handle_pragma_push_macro);
|
|
||||||
c_register_pragma (0 ,"pop_macro", handle_pragma_pop_macro);
|
|
||||||
#endif
|
|
||||||
#ifdef HANDLE_PRAGMA_WEAK
|
#ifdef HANDLE_PRAGMA_WEAK
|
||||||
c_register_pragma (0, "weak", handle_pragma_weak);
|
c_register_pragma (0, "weak", handle_pragma_weak);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -127,8 +127,6 @@ along with GCC; see the file COPYING3. If not see
|
||||||
|
|
||||||
/* Enable parsing of #pragma pack(push,<n>) and #pragma pack(pop). */
|
/* Enable parsing of #pragma pack(push,<n>) and #pragma pack(pop). */
|
||||||
#define HANDLE_PRAGMA_PACK_PUSH_POP 1
|
#define HANDLE_PRAGMA_PACK_PUSH_POP 1
|
||||||
/* Enable push_macro & pop_macro */
|
|
||||||
#define HANDLE_PRAGMA_PUSH_POP_MACRO 1
|
|
||||||
|
|
||||||
union tree_node;
|
union tree_node;
|
||||||
#define TREE union tree_node *
|
#define TREE union tree_node *
|
||||||
|
|
|
@ -10476,18 +10476,6 @@ This must be a value that would also be valid to use with
|
||||||
@samp{#pragma pack()} (that is, a small power of two).
|
@samp{#pragma pack()} (that is, a small power of two).
|
||||||
@end defmac
|
@end defmac
|
||||||
|
|
||||||
@findex #pragma
|
|
||||||
@findex pragma
|
|
||||||
@defmac HANDLE_PRAGMA_PUSH_POP_MACRO
|
|
||||||
Define this macro if you want to support the Win32 style pragmas
|
|
||||||
@samp{#pragma push_macro(macro-name-as-string)} and @samp{#pragma
|
|
||||||
pop_macro(macro-name-as-string)}. The @samp{#pragma push_macro(
|
|
||||||
macro-name-as-string)} pragma saves the named macro and via
|
|
||||||
@samp{#pragma pop_macro(macro-name-as-string)} it will return to the
|
|
||||||
previous value.
|
|
||||||
@end defmac
|
|
||||||
|
|
||||||
|
|
||||||
@defmac DOLLARS_IN_IDENTIFIERS
|
@defmac DOLLARS_IN_IDENTIFIERS
|
||||||
Define this macro to control use of the character @samp{$} in
|
Define this macro to control use of the character @samp{$} in
|
||||||
identifier names for the C family of languages. 0 means @samp{$} is
|
identifier names for the C family of languages. 0 means @samp{$} is
|
||||||
|
|
|
@ -1,4 +1,10 @@
|
||||||
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.
|
||||||
|
|
||||||
2009-11-11 Jon Beniston <jon@beniston.com>
|
2009-11-11 Jon Beniston <jon@beniston.com>
|
||||||
|
|
||||||
* lib/target-supports.exp (check_profiling_available): lm32 target
|
* lib/target-supports.exp (check_profiling_available): lm32 target
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
/* Do the preprocessor push_macro/pop_macro test. */
|
||||||
|
|
||||||
|
/* { dg-do run } */
|
||||||
|
|
||||||
|
extern "C" void abort ();
|
||||||
|
|
||||||
|
#define _ 2
|
||||||
|
#pragma push_macro("_")
|
||||||
|
#undef _
|
||||||
|
#define _ 1
|
||||||
|
#pragma pop_macro("_")
|
||||||
|
|
||||||
|
int main ()
|
||||||
|
{
|
||||||
|
if (_ != 2)
|
||||||
|
abort ();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
extern void abort ();
|
||||||
|
|
||||||
|
#define _ 2
|
||||||
|
#pragma push_macro("_")
|
||||||
|
#undef _
|
||||||
|
#define _ 1
|
||||||
|
#pragma pop_macro("_")
|
||||||
|
|
||||||
|
int main ()
|
||||||
|
{
|
||||||
|
if (_ != 2)
|
||||||
|
abort ();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* PR preprocessor/35061 */
|
/* PR preprocessor/35061 */
|
||||||
/* Do nothing if there is nothing on the macro stack to pop. */
|
/* Do nothing if there is nothing on the macro stack to pop. */
|
||||||
|
|
||||||
/* { dg-do preprocess { target *-*-mingw* *-*-cygwin* } } */
|
/* { dg-do preprocess } */
|
||||||
|
|
||||||
#define X 1
|
#define X 1
|
||||||
/* # pragma push_macro("X") */
|
/* # pragma push_macro("X") */
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
#include "pushpop-1.hs"
|
||||||
|
|
||||||
|
#if FOO != 2
|
||||||
|
#error FOO != 2
|
||||||
|
#endif
|
||||||
|
#pragma pop_macro("FOO")
|
||||||
|
|
||||||
|
#if FOO != 1
|
||||||
|
#error FOR != 1
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
#define FOO 1
|
||||||
|
#pragma push_macro ("FOO")
|
||||||
|
#undef FOO
|
||||||
|
#define FOO 2
|
||||||
|
|
|
@ -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>
|
2009-10-19 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
* charset.c (cpp_init_iconv): Initialize utf8_cset_desc.
|
* charset.c (cpp_init_iconv): Initialize utf8_cset_desc.
|
||||||
|
|
|
@ -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 cpp_hashnode *parse_assertion (cpp_reader *, struct answer **, int);
|
||||||
static struct answer ** find_answer (cpp_hashnode *, const struct answer *);
|
static struct answer ** find_answer (cpp_hashnode *, const struct answer *);
|
||||||
static void handle_assertion (cpp_reader *, const char *, int);
|
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
|
/* This is the table of directive handlers. It is ordered by
|
||||||
frequency of occurrence; the numbers at the end are directive
|
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. */
|
/* Pragmas in the global namespace. */
|
||||||
register_pragma_internal (pfile, 0, "once", do_pragma_once);
|
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. */
|
/* New GCC-specific pragmas should be put in the GCC namespace. */
|
||||||
register_pragma_internal (pfile, "GCC", "poison", do_pragma_poison);
|
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);
|
_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
|
/* Handle #pragma GCC poison, to poison one or more identifiers so
|
||||||
that the lexer produces a hard error for each subsequent usage. */
|
that the lexer produces a hard error for each subsequent usage. */
|
||||||
static void
|
static void
|
||||||
|
@ -2225,28 +2319,11 @@ cpp_undef (cpp_reader *pfile, const char *macro)
|
||||||
run_directive (pfile, T_UNDEF, buf, len);
|
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. */
|
/* If STR is a defined macro, return its definition node, else return NULL. */
|
||||||
cpp_macro *
|
cpp_macro *
|
||||||
cpp_push_definition (cpp_reader *pfile, const char *str)
|
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)
|
if (node && node->type == NT_MACRO)
|
||||||
return node->value.macro;
|
return node->value.macro;
|
||||||
else
|
else
|
||||||
|
@ -2258,7 +2335,7 @@ cpp_push_definition (cpp_reader *pfile, const char *str)
|
||||||
void
|
void
|
||||||
cpp_pop_definition (cpp_reader *pfile, const char *str, cpp_macro *dfn)
|
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)
|
if (node == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -216,6 +216,9 @@ cpp_create_reader (enum c_lang lang, hash_table *table,
|
||||||
pfile->a_buff = _cpp_get_buff (pfile, 0);
|
pfile->a_buff = _cpp_get_buff (pfile, 0);
|
||||||
pfile->u_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. */
|
/* The expression parser stack. */
|
||||||
_cpp_expand_op_stack (pfile);
|
_cpp_expand_op_stack (pfile);
|
||||||
|
|
||||||
|
@ -245,6 +248,7 @@ void
|
||||||
cpp_destroy (cpp_reader *pfile)
|
cpp_destroy (cpp_reader *pfile)
|
||||||
{
|
{
|
||||||
cpp_context *context, *contextn;
|
cpp_context *context, *contextn;
|
||||||
|
struct def_pragma_macro *pmacro;
|
||||||
tokenrun *run, *runn;
|
tokenrun *run, *runn;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -296,6 +300,17 @@ cpp_destroy (cpp_reader *pfile)
|
||||||
|
|
||||||
free (pfile->comments.entries);
|
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);
|
free (pfile);
|
||||||
}
|
}
|
||||||
|
|
|
@ -305,6 +305,16 @@ struct cpp_buffer
|
||||||
struct cset_converter input_cset_desc;
|
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.
|
/* A cpp_reader encapsulates the "state" of a pre-processor run.
|
||||||
Applying cpp_get_token repeatedly yields a stream of pre-processor
|
Applying cpp_get_token repeatedly yields a stream of pre-processor
|
||||||
tokens. Usually, there is only one cpp_reader object active. */
|
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. */
|
/* Table of comments, when state.save_comments is true. */
|
||||||
cpp_comment_table comments;
|
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.
|
/* 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 cpp_token *_cpp_lex_direct (cpp_reader *);
|
||||||
extern int _cpp_equiv_tokens (const cpp_token *, const cpp_token *);
|
extern int _cpp_equiv_tokens (const cpp_token *, const cpp_token *);
|
||||||
extern void _cpp_init_tokenrun (tokenrun *, unsigned int);
|
extern void _cpp_init_tokenrun (tokenrun *, unsigned int);
|
||||||
|
extern cpp_hashnode *_cpp_lex_identifier (cpp_reader *, const char *);
|
||||||
|
|
||||||
/* In init.c. */
|
/* In init.c. */
|
||||||
extern void _cpp_maybe_push_include_file (cpp_reader *);
|
extern void _cpp_maybe_push_include_file (cpp_reader *);
|
||||||
|
|
57
libcpp/lex.c
57
libcpp/lex.c
|
@ -504,6 +504,63 @@ forms_identifier_p (cpp_reader *pfile, int first,
|
||||||
return false;
|
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. */
|
/* Lex an identifier starting at BUFFER->CUR - 1. */
|
||||||
static cpp_hashnode *
|
static cpp_hashnode *
|
||||||
lex_identifier (cpp_reader *pfile, const uchar *base, bool starts_ucn,
|
lex_identifier (cpp_reader *pfile, const uchar *base, bool starts_ucn,
|
||||||
|
|
136
libcpp/pch.c
136
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 collect_ht_nodes (cpp_reader *, cpp_hashnode *, void *);
|
||||||
static int write_defs (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 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. */
|
/* This structure represents a macro definition on disk. */
|
||||||
struct macrodef_struct
|
struct macrodef_struct
|
||||||
|
@ -378,9 +380,140 @@ cpp_write_pch_state (cpp_reader *r, FILE *f)
|
||||||
return -1;
|
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;
|
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 */
|
/* 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)
|
if (!r->counter)
|
||||||
r->counter = counter;
|
r->counter = counter;
|
||||||
|
|
||||||
|
/* Read pushed macros. */
|
||||||
|
if (! _cpp_restore_pushed_macros (r, f))
|
||||||
|
goto error;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
|
Loading…
Reference in New Issue