Commit fc009f96 by Geoff Keating Committed by Geoffrey Keating

Makefile.in (cppexp.o): Depend on cpphash.h.

	* Makefile.in (cppexp.o): Depend on cpphash.h.
	* cppexp.c (cpp_lex): Handle `defined (xxx)' for poisoned xxx.
	Include cpphash.h.
	* cpphash.c (special_symbol): Handle plain `xxx' for poisoned xxx.
	* cpplib.c (do_define): Generalise to handle poisoned definitions,
	redefining poisoned identifiers, etc.
	(do_undef): Don't allow poisoned identifiers to be undefined.
	(do_pragma): Add #pragma poison.
	(do_xifdef): Handle `#ifdef xxx' for poisoned xxx.

	* cccp.c: Add T_POISON node type.
	(special_symbol): Handle `defined(xxx)' and plain `xxx' for
	poisoned xxx.
	(do_define): Generalise to handle poisoned definitions,
	redefining poisoned identifiers, etc.
	(do_undef): Don't allow poisoned identifiers to be undefined.
	(do_pragma): Add #pragma poison.
	(do_xifdef): Handle `#ifdef xxx' for poisoned xxx.

	* c-pragma.c (handle_pragma_token): Ignore #pragma poison.
	* c-pragma.h: Add ps_poison state.  We now always have generic
	pragmas.

From-SVN: r29224
parent d60f72ae
Thu Sep 9 13:46:06 1999 Geoffrey Keating <geoffk@cygnus.com>
* Makefile.in (cppexp.o): Depend on cpphash.h.
* cppexp.c (cpp_lex): Handle `defined (xxx)' for poisoned xxx.
Include cpphash.h.
* cpphash.c (special_symbol): Handle plain `xxx' for poisoned xxx.
* cpplib.c (do_define): Generalise to handle poisoned definitions,
redefining poisoned identifiers, etc.
(do_undef): Don't allow poisoned identifiers to be undefined.
(do_pragma): Add #pragma poison.
(do_xifdef): Handle `#ifdef xxx' for poisoned xxx.
* cccp.c: Add T_POISON node type.
(special_symbol): Handle `defined(xxx)' and plain `xxx' for
poisoned xxx.
(do_define): Generalise to handle poisoned definitions,
redefining poisoned identifiers, etc.
(do_undef): Don't allow poisoned identifiers to be undefined.
(do_pragma): Add #pragma poison.
(do_xifdef): Handle `#ifdef xxx' for poisoned xxx.
* c-pragma.c (handle_pragma_token): Ignore #pragma poison.
* c-pragma.h: Add ps_poison state. We now always have generic
pragmas.
Wed Sep 8 20:30:42 1999 Mark Mitchell <mark@codesourcery.com> Wed Sep 8 20:30:42 1999 Mark Mitchell <mark@codesourcery.com>
* ggc.h (ggc_alloc): New function. * ggc.h (ggc_alloc): New function.
......
...@@ -2019,7 +2019,7 @@ cpplib.o: cpplib.c $(CONFIG_H) cpplib.h intl.h system.h cpphash.h ...@@ -2019,7 +2019,7 @@ cpplib.o: cpplib.c $(CONFIG_H) cpplib.h intl.h system.h cpphash.h
cpphash.o: cpphash.c $(CONFIG_H) cpplib.h intl.h system.h cpphash.h cpphash.o: cpphash.c $(CONFIG_H) cpplib.h intl.h system.h cpphash.h
cppalloc.o: cppalloc.c $(CONFIG_H) cpplib.h intl.h system.h cppalloc.o: cppalloc.c $(CONFIG_H) cpplib.h intl.h system.h
cpperror.o: cpperror.c $(CONFIG_H) cpplib.h intl.h system.h cpperror.o: cpperror.c $(CONFIG_H) cpplib.h intl.h system.h
cppexp.o: cppexp.c $(CONFIG_H) cpplib.h intl.h system.h cppexp.o: cppexp.c $(CONFIG_H) cpplib.h intl.h system.h cpphash.h
cppfiles.o: cppfiles.c $(CONFIG_H) cpplib.h intl.h system.h cppfiles.o: cppfiles.c $(CONFIG_H) cpplib.h intl.h system.h
cppinit.o: cppinit.c $(CONFIG_H) cpplib.h intl.h system.h \ cppinit.o: cppinit.c $(CONFIG_H) cpplib.h intl.h system.h \
......
...@@ -300,6 +300,10 @@ handle_pragma_token (string, token) ...@@ -300,6 +300,10 @@ handle_pragma_token (string, token)
ret_val = 1; /* Ignore the pragma. */ ret_val = 1; /* Ignore the pragma. */
break; break;
#endif /* HANDLE_PRAGMA_WEAK */ #endif /* HANDLE_PRAGMA_WEAK */
case ps_poison:
ret_val = 1;
break;
} }
type = state = ps_start; type = state = ps_start;
...@@ -338,9 +342,11 @@ handle_pragma_token (string, token) ...@@ -338,9 +342,11 @@ handle_pragma_token (string, token)
#ifdef HANDLE_PRAGMA_WEAK #ifdef HANDLE_PRAGMA_WEAK
if (strcmp (string, "weak") == 0) if (strcmp (string, "weak") == 0)
type = state = ps_weak; type = state = ps_weak;
#endif #endif
if (strcmp (string, "poison") == 0)
type = state = ps_poison;
break; break;
#ifdef HANDLE_PRAGMA_WEAK #ifdef HANDLE_PRAGMA_WEAK
case ps_weak: case ps_weak:
name = permalloc (strlen (string) + 1); name = permalloc (strlen (string) + 1);
...@@ -485,7 +491,12 @@ handle_pragma_token (string, token) ...@@ -485,7 +491,12 @@ handle_pragma_token (string, token)
state = ps_bad; state = ps_bad;
break; break;
#endif /* HANDLE_PRAGMA_PACK_PUSH_POP */ #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
case ps_poison:
if (token && TREE_CODE (token) != IDENTIFIER_NODE)
state = ps_bad;
break;
case ps_bad: case ps_bad:
case ps_done: case ps_done:
break; break;
......
...@@ -61,13 +61,12 @@ extern int add_weak PROTO((char *, char *)); ...@@ -61,13 +61,12 @@ extern int add_weak PROTO((char *, char *));
#endif /* HANDLE_PRAGMA_WEAK */ #endif /* HANDLE_PRAGMA_WEAK */
#if defined HANDLE_PRAGMA_PACK || defined HANDLE_PRAGMA_WEAK
/* Define HANDLE_GENERIC_PRAGMAS if any kind of front-end pragma /* Define HANDLE_GENERIC_PRAGMAS if any kind of front-end pragma
parsing is to be done. The code in GCC's generic C source files parsing is to be done. The code in GCC's generic C source files
will only look for the definition of this constant. They will will only look for the definition of this constant. They will
ignore definitions of HANDLE_PRAGMA_PACK and so on. */ ignore definitions of HANDLE_PRAGMA_PACK and so on.
With #pragma poison, this is always set. */
#define HANDLE_GENERIC_PRAGMAS 1 #define HANDLE_GENERIC_PRAGMAS 1
#endif
#ifdef HANDLE_GENERIC_PRAGMAS #ifdef HANDLE_GENERIC_PRAGMAS
...@@ -91,6 +90,7 @@ enum pragma_state ...@@ -91,6 +90,7 @@ enum pragma_state
ps_push, ps_pushcomma, ps_pushid, ps_pushcomma2, ps_push, ps_pushcomma, ps_pushid, ps_pushcomma2,
ps_pop, ps_popcomma, ps_pop, ps_popcomma,
#endif #endif
ps_poison,
ps_bad ps_bad
}; };
......
...@@ -640,6 +640,7 @@ enum node_type { ...@@ -640,6 +640,7 @@ enum node_type {
T_DISABLED, /* macro temporarily turned off for rescan */ T_DISABLED, /* macro temporarily turned off for rescan */
T_SPEC_DEFINED, /* special `defined' macro for use in #if statements */ T_SPEC_DEFINED, /* special `defined' macro for use in #if statements */
T_PCSTRING, /* precompiled string (hashval is KEYDEF *) */ T_PCSTRING, /* precompiled string (hashval is KEYDEF *) */
T_POISON, /* defined with `#pragma poison' */
T_UNUSED /* Used for something not defined. */ T_UNUSED /* Used for something not defined. */
}; };
...@@ -4281,7 +4282,12 @@ special_symbol (hp, op) ...@@ -4281,7 +4282,12 @@ special_symbol (hp, op)
|| (hp->type == T_MACRO && hp->value.defn->predefined))) || (hp->type == T_MACRO && hp->value.defn->predefined)))
/* Output a precondition for this macro use. */ /* Output a precondition for this macro use. */
fprintf (pcp_outfile, "#define %s\n", hp->name); fprintf (pcp_outfile, "#define %s\n", hp->name);
buf = " 1 "; if (hp->type == T_POISON) {
error("attempt to use poisoned `%s'.", hp->name);
buf = " 0 ";
} else {
buf = " 1 ";
}
} }
else else
if (pcp_outfile && pcp_inside_if) { if (pcp_outfile && pcp_inside_if) {
...@@ -4302,6 +4308,11 @@ special_symbol (hp, op) ...@@ -4302,6 +4308,11 @@ special_symbol (hp, op)
} }
break; break;
case T_POISON:
error("attempt to use poisoned `%s'.", hp->name);
buf = " 0 "; /* Consider poisoned symbol to not be defined */
break;
oops: oops:
error ("`defined' without an identifier"); error ("`defined' without an identifier");
...@@ -5926,6 +5937,7 @@ do_define (buf, limit, op, keyword) ...@@ -5926,6 +5937,7 @@ do_define (buf, limit, op, keyword)
{ {
int hashcode; int hashcode;
MACRODEF mdef; MACRODEF mdef;
enum node_type newtype = keyword->type == T_DEFINE ? T_MACRO : T_POISON;
/* If this is a precompiler run (with -pcp) pass thru #define directives. */ /* If this is a precompiler run (with -pcp) pass thru #define directives. */
if (pcp_outfile && op) if (pcp_outfile && op)
...@@ -5944,35 +5956,50 @@ do_define (buf, limit, op, keyword) ...@@ -5944,35 +5956,50 @@ do_define (buf, limit, op, keyword)
/* Redefining a precompiled key is ok. */ /* Redefining a precompiled key is ok. */
if (hp->type == T_PCSTRING) if (hp->type == T_PCSTRING)
ok = 1; ok = 1;
/* Redefining a poisoned identifier is even worse than `not ok'. */
else if (hp->type == T_POISON)
ok = -1;
/* Poisoning anything else is not ok.
The poison should always come first. */
else if (newtype == T_POISON)
ok = 0;
/* Redefining a macro is ok if the definitions are the same. */ /* Redefining a macro is ok if the definitions are the same. */
else if (hp->type == T_MACRO) else if (hp->type == T_MACRO)
ok = ! compare_defs (mdef.defn, hp->value.defn); ok = ! compare_defs (mdef.defn, hp->value.defn);
/* Redefining a constant is ok with -D. */ /* Redefining a constant is ok with -D. */
else if (hp->type == T_CONST) else if (hp->type == T_CONST)
ok = ! done_initializing; ok = ! done_initializing;
/* Print the warning if it's not ok. */
if (!ok) { /* Print the warning or error if it's not ok. */
/* If we are passing through #define and #undef directives, do if (ok <= 0)
that for this re-definition now. */ {
if (debug_output && op) /* If we are passing through #define and #undef directives, do
pass_thru_directive (buf, limit, op, keyword); that for this re-definition now. */
if (debug_output && op)
pedwarn ("`%.*s' redefined", mdef.symlen, mdef.symnam); pass_thru_directive (buf, limit, op, keyword);
if (hp->type == T_MACRO)
pedwarn_with_file_and_line (hp->value.defn->file, if (hp->type == T_POISON)
hp->value.defn->file_len, error ("redefining poisoned `%.*s'", mdef.symlen, mdef.symnam);
hp->value.defn->line, else
"this is the location of the previous definition"); pedwarn ("`%.*s' redefined", mdef.symlen, mdef.symnam);
} if (hp->type == T_MACRO)
/* Replace the old definition. */ pedwarn_with_file_and_line (hp->value.defn->file,
hp->type = T_MACRO; hp->value.defn->file_len,
hp->value.defn = mdef.defn; hp->value.defn->line,
"this is the location of the previous definition");
}
if (hp->type != T_POISON)
{
/* Replace the old definition. */
hp->type = newtype;
hp->value.defn = mdef.defn;
}
} else { } else {
/* If we are passing through #define and #undef directives, do /* If we are passing through #define and #undef directives, do
that for this new definition now. */ that for this new definition now. */
if (debug_output && op) if (debug_output && op)
pass_thru_directive (buf, limit, op, keyword); pass_thru_directive (buf, limit, op, keyword);
install (mdef.symnam, mdef.symlen, T_MACRO, install (mdef.symnam, mdef.symlen, newtype,
(char *) mdef.defn, hashcode); (char *) mdef.defn, hashcode);
} }
} }
...@@ -6990,9 +7017,13 @@ do_undef (buf, limit, op, keyword) ...@@ -6990,9 +7017,13 @@ do_undef (buf, limit, op, keyword)
need to pass through all effective #undef directives. */ need to pass through all effective #undef directives. */
if (debug_output && op) if (debug_output && op)
pass_thru_directive (orig_buf, limit, op, keyword); pass_thru_directive (orig_buf, limit, op, keyword);
if (hp->type != T_MACRO) if (hp->type == T_POISON)
warning ("undefining `%s'", hp->name); error ("cannot undefine poisoned `%s'", hp->name);
delete_macro (hp); else {
if (hp->type != T_MACRO)
warning ("undefining `%s'", hp->name);
delete_macro (hp);
}
} }
if (pedantic) { if (pedantic) {
...@@ -7087,9 +7118,9 @@ do_ident (buf, limit, op, keyword) ...@@ -7087,9 +7118,9 @@ do_ident (buf, limit, op, keyword)
static int static int
do_pragma (buf, limit, op, keyword) do_pragma (buf, limit, op, keyword)
U_CHAR *buf, *limit ATTRIBUTE_UNUSED; U_CHAR *buf, *limit;
FILE_BUF *op ATTRIBUTE_UNUSED; FILE_BUF *op;
struct directive *keyword ATTRIBUTE_UNUSED; struct directive *keyword;
{ {
SKIP_WHITE_SPACE (buf); SKIP_WHITE_SPACE (buf);
if (!strncmp ((char *) buf, "once", 4)) { if (!strncmp ((char *) buf, "once", 4)) {
...@@ -7100,6 +7131,29 @@ do_pragma (buf, limit, op, keyword) ...@@ -7100,6 +7131,29 @@ do_pragma (buf, limit, op, keyword)
do_once (); do_once ();
} }
if (!strncmp (buf, "poison", 6)) {
/* Poison these symbols so that all subsequent usage produces an
error message. */
U_CHAR *p = buf + 6;
SKIP_WHITE_SPACE (p);
while (p < limit)
{
U_CHAR *end = p;
while (end < limit && is_idchar[*end])
end++;
if (end < limit && !is_space[*end])
{
error ("invalid #pragma poison");
return 0;
}
do_define(p, end, op, keyword);
p = end;
SKIP_WHITE_SPACE (p);
}
}
if (!strncmp ((char *) buf, "implementation", 14)) { if (!strncmp ((char *) buf, "implementation", 14)) {
/* Be quiet about `#pragma implementation' for a file only if it hasn't /* Be quiet about `#pragma implementation' for a file only if it hasn't
been included yet. */ been included yet. */
...@@ -7351,6 +7405,10 @@ do_xifdef (buf, limit, op, keyword) ...@@ -7351,6 +7405,10 @@ do_xifdef (buf, limit, op, keyword)
} }
} }
if ((hp != NULL) && (hp->type == T_POISON)) {
error("attempt to use poisoned `%s'.", hp->name);
hp = NULL;
}
skip = (hp == NULL) ^ (keyword->type == T_IFNDEF); skip = (hp == NULL) ^ (keyword->type == T_IFNDEF);
if (start_of_file && !skip) { if (start_of_file && !skip) {
control_macro = (U_CHAR *) xmalloc (end - buf + 1); control_macro = (U_CHAR *) xmalloc (end - buf + 1);
......
...@@ -551,6 +551,7 @@ in the C preprocessor. ...@@ -551,6 +551,7 @@ in the C preprocessor.
* Concatenation:: Building tokens from parts taken from macro arguments. * Concatenation:: Building tokens from parts taken from macro arguments.
* Undefining:: Cancelling a macro's definition. * Undefining:: Cancelling a macro's definition.
* Redefining:: Changing a macro's definition. * Redefining:: Changing a macro's definition.
* Poisoning:: Ensuring a macro is never defined or used.
* Macro Pitfalls:: Macros can confuse the unwary. Here we explain * Macro Pitfalls:: Macros can confuse the unwary. Here we explain
several common problems and strange features. several common problems and strange features.
@end menu @end menu
...@@ -1370,7 +1371,7 @@ The same form of @samp{#undef} directive will cancel definitions with ...@@ -1370,7 +1371,7 @@ The same form of @samp{#undef} directive will cancel definitions with
arguments or definitions that don't expect arguments. The @samp{#undef} arguments or definitions that don't expect arguments. The @samp{#undef}
directive has no effect when used on a name not currently defined as a macro. directive has no effect when used on a name not currently defined as a macro.
@node Redefining, Macro Pitfalls, Undefining, Macros @node Redefining, Poisoning, Undefining, Macros
@subsection Redefining Macros @subsection Redefining Macros
@cindex redefining macros @cindex redefining macros
...@@ -1404,7 +1405,28 @@ where there was no whitespace at all. ...@@ -1404,7 +1405,28 @@ where there was no whitespace at all.
Recall that a comment counts as whitespace. Recall that a comment counts as whitespace.
@node Macro Pitfalls,, Redefining, Macros @node Poisoning, Macro Pitfalls, Redefining, Macros
@subsection Poisoning Macros
@cindex poisoning macros
Sometimes, there is an identifier that you want to remove completely
from your program, and make sure that it never creeps back in. To
enforce this, the @samp{#pragma poison} directive can be used.
@samp{#pragma poison} is followed by a list of identifiers to poison,
and takes effect for the rest of the source. You cannot @samp{#undef} a
poisoned identifier or test to see if it's defined with @samp{#ifdef}.
For example,
@example
#pragma poison printf sprintf fprintf
sprintf(some_string, "hello");
@end example
@noindent
will produce an error.
@node Macro Pitfalls,, Poisoning, Macros
@subsection Pitfalls and Subtleties of Macros @subsection Pitfalls and Subtleties of Macros
@cindex problems with macros @cindex problems with macros
@cindex pitfalls of macros @cindex pitfalls of macros
......
...@@ -27,6 +27,7 @@ Written by Per Bothner 1994. */ ...@@ -27,6 +27,7 @@ Written by Per Bothner 1994. */
#include "config.h" #include "config.h"
#include "system.h" #include "system.h"
#include "cpplib.h" #include "cpplib.h"
#include "cpphash.h"
#ifdef MULTIBYTE_CHARS #ifdef MULTIBYTE_CHARS
#include <locale.h> #include <locale.h>
...@@ -445,6 +446,7 @@ cpp_lex (pfile, skip_evaluation) ...@@ -445,6 +446,7 @@ cpp_lex (pfile, skip_evaluation)
int paren = 0, len; int paren = 0, len;
cpp_buffer *ip = CPP_BUFFER (pfile); cpp_buffer *ip = CPP_BUFFER (pfile);
U_CHAR *tok; U_CHAR *tok;
HASHNODE *hp;
cpp_skip_hspace (pfile); cpp_skip_hspace (pfile);
if (*ip->cur == '(') if (*ip->cur == '(')
...@@ -469,9 +471,14 @@ cpp_lex (pfile, skip_evaluation) ...@@ -469,9 +471,14 @@ cpp_lex (pfile, skip_evaluation)
goto oops; goto oops;
++ip->cur; ++ip->cur;
} }
if (cpp_lookup (pfile, tok, len, -1)) hp = cpp_lookup (pfile, tok, len, -1);
op.value = 1; if (hp != NULL)
{
if (hp->type == T_POISON)
cpp_error (pfile, "attempt to use poisoned `%s'", hp->name);
else
op.value = 1;
}
} }
return op; return op;
......
...@@ -1020,6 +1020,13 @@ special_symbol (hp, pfile) ...@@ -1020,6 +1020,13 @@ special_symbol (hp, pfile)
return; return;
} }
case T_POISON:
cpp_error (pfile, "attempt to use poisoned `%s'.", hp->name);
CPP_RESERVE (pfile, 1);
CPP_PUTC_Q (pfile, '0');
CPP_NUL_TERMINATE_Q (pfile);
break;
default: default:
cpp_fatal (pfile, "cpplib internal error: invalid special hash type"); cpp_fatal (pfile, "cpplib internal error: invalid special hash type");
return; return;
......
...@@ -625,8 +625,9 @@ check_macro_name (pfile, symname, assertion) ...@@ -625,8 +625,9 @@ check_macro_name (pfile, symname, assertion)
} }
/* Process a #define command. /* Process a #define command.
KEYWORD is the keyword-table entry for #define, KEYWORD is the keyword-table entry for #define,
or NULL for a "predefined" macro. */ or NULL for a "predefined" macro,
or the keyword-table entry for #pragma in the case of a #pragma poison. */
static int static int
do_define (pfile, keyword) do_define (pfile, keyword)
...@@ -638,10 +639,16 @@ do_define (pfile, keyword) ...@@ -638,10 +639,16 @@ do_define (pfile, keyword)
HASHNODE *hp; HASHNODE *hp;
long here; long here;
U_CHAR *macro, *buf, *end; U_CHAR *macro, *buf, *end;
enum node_type new_type;
here = CPP_WRITTEN (pfile); here = CPP_WRITTEN (pfile);
copy_rest_of_line (pfile); copy_rest_of_line (pfile);
if (keyword == NULL || keyword->type == T_DEFINE)
new_type = T_MACRO;
else
new_type = T_POISON;
/* Copy out the line so we can pop the token buffer. */ /* Copy out the line so we can pop the token buffer. */
buf = pfile->token_buffer + here; buf = pfile->token_buffer + here;
end = CPP_PWRITTEN (pfile); end = CPP_PWRITTEN (pfile);
...@@ -663,30 +670,40 @@ do_define (pfile, keyword) ...@@ -663,30 +670,40 @@ do_define (pfile, keyword)
/* Redefining a precompiled key is ok. */ /* Redefining a precompiled key is ok. */
if (hp->type == T_PCSTRING) if (hp->type == T_PCSTRING)
ok = 1; ok = 1;
/* Redefining a poisoned identifier is even worse than `not ok'. */
else if (hp->type == T_POISON)
ok = -1;
/* Redefining a macro is ok if the definitions are the same. */ /* Redefining a macro is ok if the definitions are the same. */
else if (hp->type == T_MACRO) else if (hp->type == T_MACRO)
ok = ! compare_defs (pfile, mdef.defn, hp->value.defn); ok = ! compare_defs (pfile, mdef.defn, hp->value.defn);
/* Redefining a constant is ok with -D. */ /* Redefining a constant is ok with -D. */
else if (hp->type == T_CONST || hp->type == T_STDC) else if (hp->type == T_CONST || hp->type == T_STDC)
ok = ! CPP_OPTIONS (pfile)->done_initializing; ok = ! CPP_OPTIONS (pfile)->done_initializing;
/* Print the warning if it's not ok. */ /* Print the warning or error if it's not ok. */
if (!ok) if (ok <= 0)
{ {
cpp_pedwarn (pfile, "`%.*s' redefined", mdef.symlen, mdef.symnam); if (hp->type == T_POISON)
cpp_error (pfile, "redefining poisoned `%.*s'",
mdef.symlen, mdef.symnam);
else
cpp_pedwarn (pfile, "`%.*s' redefined", mdef.symlen, mdef.symnam);
if (hp->type == T_MACRO) if (hp->type == T_MACRO)
cpp_pedwarn_with_file_and_line (pfile, hp->value.defn->file, cpp_pedwarn_with_file_and_line (pfile, hp->value.defn->file,
hp->value.defn->line, hp->value.defn->line,
"this is the location of the previous definition"); "this is the location of the previous definition");
} }
/* Replace the old definition. */ if (hp->type != T_POISON)
hp->type = T_MACRO; {
hp->value.defn = mdef.defn; /* Replace the old definition. */
hp->type = new_type;
hp->value.defn = mdef.defn;
}
} }
else else
cpp_install (pfile, mdef.symnam, mdef.symlen, T_MACRO, cpp_install (pfile, mdef.symnam, mdef.symlen, new_type,
(char *) mdef.defn, hashcode); (char *) mdef.defn, hashcode);
if (keyword) if (keyword != NULL && keyword->type == T_DEFINE)
{ {
if (CPP_OPTIONS (pfile)->debug_output if (CPP_OPTIONS (pfile)->debug_output
|| CPP_OPTIONS (pfile)->dump_macros == dump_definitions) || CPP_OPTIONS (pfile)->dump_macros == dump_definitions)
...@@ -1425,9 +1442,14 @@ do_undef (pfile, keyword) ...@@ -1425,9 +1442,14 @@ do_undef (pfile, keyword)
need to pass through all effective #undef commands. */ need to pass through all effective #undef commands. */
if (CPP_OPTIONS (pfile)->debug_output && keyword) if (CPP_OPTIONS (pfile)->debug_output && keyword)
pass_thru_directive (name, sym_length, pfile, keyword); pass_thru_directive (name, sym_length, pfile, keyword);
if (hp->type != T_MACRO) if (hp->type == T_POISON)
cpp_warning (pfile, "undefining `%s'", hp->name); cpp_error (pfile, "cannot undefine poisoned `%s'", hp->name);
delete_macro (hp); else
{
if (hp->type != T_MACRO)
cpp_warning (pfile, "undefining `%s'", hp->name);
delete_macro (hp);
}
} }
return 0; return 0;
...@@ -1579,6 +1601,65 @@ do_pragma (pfile, keyword) ...@@ -1579,6 +1601,65 @@ do_pragma (pfile, keyword)
"`#pragma implementation' for `%s' appears after file is included", "`#pragma implementation' for `%s' appears after file is included",
fcopy); fcopy);
} }
else if (!strncmp (buf, "poison", 6))
{
/* Poison these symbols so that all subsequent usage produces an
error message. */
U_CHAR *p = buf + 6;
size_t plen;
U_CHAR *syms;
int writeit;
SKIP_WHITE_SPACE (p);
plen = strlen(p) + 1;
syms = (U_CHAR *) alloca (plen);
memcpy (syms, p, plen);
/* As a rule, don't include #pragma poison commands in output,
unless the user asks for them. */
writeit = (CPP_OPTIONS (pfile)->debug_output
|| CPP_OPTIONS (pfile)->dump_macros == dump_definitions
|| CPP_OPTIONS (pfile)->dump_macros == dump_names);
if (writeit)
CPP_SET_WRITTEN (pfile, here);
else
CPP_SET_WRITTEN (pfile, here-8);
if (writeit)
{
CPP_RESERVE (pfile, plen + 7);
CPP_PUTS_Q (pfile, "poison", 7);
}
while (*syms != '\0')
{
U_CHAR *end = syms;
while (is_idchar[*end])
end++;
if (!is_hor_space[*end] && *end != '\0')
{
cpp_error (pfile, "invalid #pragma poison directive");
return 1;
}
if (cpp_push_buffer (pfile, syms, end - syms) != NULL)
{
do_define (pfile, keyword);
cpp_pop_buffer (pfile);
}
if (writeit)
{
CPP_PUTC_Q (pfile, ' ');
CPP_PUTS_Q (pfile, syms, end - syms);
}
syms = end;
SKIP_WHITE_SPACE (syms);
}
}
return 0; return 0;
} }
...@@ -1807,6 +1888,11 @@ do_xifdef (pfile, keyword) ...@@ -1807,6 +1888,11 @@ do_xifdef (pfile, keyword)
control_macro = (U_CHAR *) xmalloc (ident_length + 1); control_macro = (U_CHAR *) xmalloc (ident_length + 1);
bcopy (ident, control_macro, ident_length + 1); bcopy (ident, control_macro, ident_length + 1);
} }
if (hp != NULL && hp->type == T_POISON)
{
cpp_error (pfile, "attempt to use poisoned `%s'", hp->name);
skip = !skip;
}
} }
else else
{ {
......
...@@ -600,6 +600,7 @@ enum node_type { ...@@ -600,6 +600,7 @@ enum node_type {
T_MACRO, /* macro defined by `#define' */ T_MACRO, /* macro defined by `#define' */
T_DISABLED, /* macro temporarily turned off for rescan */ T_DISABLED, /* macro temporarily turned off for rescan */
T_PCSTRING, /* precompiled string (hashval is KEYDEF *) */ T_PCSTRING, /* precompiled string (hashval is KEYDEF *) */
T_POISON, /* defined with `#pragma poison' */
T_UNUSED /* Used for something not defined. */ T_UNUSED /* Used for something not defined. */
}; };
......
1999-09-08 Geoffrey Keating <geoffk@cygnus.com>
* noncompile/noncompile.exp: Add poison-1.c.
* noncompile/poison-1.c: New file.
1999-09-06 Franz Sirl <Franz.Sirl-kernel@lauterbach.com> 1999-09-06 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
* execute/va-arg-9.c: New test. * execute/va-arg-9.c: New test.
......
...@@ -323,3 +323,13 @@ set compiler_output ".*:6:" ...@@ -323,3 +323,13 @@ set compiler_output ".*:6:"
set groups {passed gcc-noncompile} set groups {passed gcc-noncompile}
postbase_with_opts $src_code $run $groups postbase_with_opts $src_code $run $groups
# Test poison-1.c
prebase
set src_code poison-1.c
set compiler_output ".*c:2:.*c:4:.*c:5:.*c:7:.*c:8:.*c:9:.*c:11:.*c:12:.*c:13:.*c:14:.*c:17:.*c:20:"
set groups {passed gcc-noncompile}
postbase $src_code $run $groups
#pragma poison foo
foo
#pragma poison foo2 foo3
foo2
foo3
#pragma poison foo4 foo5
foo4
foo5
#pragma poison +++
#define foo6 123
#pragma poison foo6
#define foo6 345
#define foo6 456
#ifdef foo6
#error hey! foo6 poisoned!
#endif
#if defined(foo6)
#error no, foo6 still poisoned!
#else
foo6
#endif
#pragma poison
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment